$NOIP2004$ 题解报告

目录

•$Luogu P1089$ 津津的储蓄计划$( √ )$

•$Luogu P1090$ 合并果子$( √ )$

•$Luogu P1091$ 合唱队形$( √ )$

•$Luogu P1092$ 虫食算$( √ )$


$Luogu P1089$ 津津的储蓄计划

题目传送门

 

$NOIP$提高组中唯一一道入门题$QwQ$

直接暴力模拟就$ok$了,放下代码就好

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int n,m,x=0,a=0,b=0,d=0;
 5     bool c=0;
 6     for(int i=1;i<=12;i++)
 7      {
 8         cin>>n;
 9         m=300+a-n;
10         if(m>=0) {x+=m/100;a=m%100;}
11         else{m=0;a=0;c=1;}
12         b++;
13         if(c==1&&d==0)
14           {d=b;c=0;}
15      }
16      if(d!=0) cout<<-d;
17      else cout<<120*x+a;
18      
19     return 0;
20 }
代码戳这里

$Luogu P1090$ 合并果子

题目传送门

可以直接用$STL$中的$priority_queue$,也可以手写堆

每次取出堆顶$($小根堆$)$的两个元素,将其和加进答案并重新插入堆

放下$STL$的代码

 1 #include<bits/stdc++.h>
 2 #define ri register int
 3 #define ll long long
 4 #define rl register ll
 5 #define go(i,a,b) for(ri i=a;i<=b;i++)
 6 #define back(i,a,b) for(ri i=a;i>=b;i--)
 7 #define g() getchar()
 8 #define il inline
 9 #define pf printf
10 #define mem(a,b) memset(a,b,sizeof(a))
11 using namespace std;
12 il int fr(){
13     ri w=0,q=1;char ch=g();
14     while(ch<'0'||ch>'9'){if(ch=='-')q=-1;ch=g();}
15     while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=g();
16     return w*q;
17 }
18 int n,ans;
19 priority_queue<int>q;
20 int main(){
21     //freopen(".in","r",stdin);
22     //freopen(".out","w",stdout);
23     n=fr();
24     go(i,1,n){
25         ri a=fr();
26         q.push(-a);
27     }
28     while(q.size()>1){
29         ri x=q.top();q.pop();x=-x;
30         ri y=q.top();q.pop();y=-y;
31         ans+=x+y;x+=y;
32         q.push(-x);
33     }
34     if(!ans)ans+=q.top();
35     pf("%d
",ans);
36     return 0;
37 }
STL版

$Luogu P1092$ 合唱队形

题目传送门

设$b[i]$表示正着数到第$i$个人,包括第$i$个人在内最多能留下多少个人,$c[i]$表示倒着数

最后枚举中间的分界点,使得$b[i]+c[i]$最大,答案为$n-max{b[i]+c[i]}+1$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[200],b[200],c[200];
 4 int main(){
 5     int n,i,j,maxx;
 6     cin>>n;
 7     memset(b,0,sizeof(b));
 8     memset(c,0,sizeof(c));
 9     for(i=1;i<=n;i++)
10       cin>>a[i];
11     for(i=1;i<=n;i++)
12      {
13          b[i]=1;
14          for(j=1;j<=i-1;j++)
15            if((a[i]>a[j])&&(b[j]+1>b[i])) b[i]=b[j]+1;
16      }
17     for(i=n;i>=1;i--)
18      {
19          c[i]=1;
20          for(j=i+1;j<=n;j++)
21            if((a[j]<a[i])&&(c[j]+1>c[i])) c[i]=c[j]+1;
22      }
23     maxx=0;
24     for(i=1;i<=n;i++)
25       if(b[i]+c[i]>maxx) maxx=b[i]+c[i];
26     cout<<n-maxx+1<<endl;
27     return 0;
28 }
代码戳这里

$Luogu P1091$ 虫食算

题目传送门

从大到小枚举每个字母代表的数字,一边枚举一边判断是否合法,$dfs+$剪枝即可$AC$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,sum[30],wait[30];
 4 char s1[30],s2[30],s3[30];
 5 bool used[30];
 6 void print(){
 7     for(int i=0;i<n;i++){
 8         if(i==0) printf("%d",sum[i]);
 9         else printf(" %d",sum[i]);
10     }
11     exit(0);
12 }
13 bool cut(){
14     if(sum[s1[0]-'A']+sum[s2[0]-'A']>=n) return 0;//如果第一位要进位显然不可能
15     for(int i=n-1;i>=0;i--){
16         int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A'];
17         if(A==-1||B==-1||C==-1) continue;
18         if((A+B)%n!=C&&(A+B+1)%n!=C) return 0;
19 //如果当前这一位加起来的数字不对,那么也要返回
20     }
21     return 1;//如果符合条件则返回1
22 }
23 bool pd(){//判断是否成立
24     int x=0;//x记录进位
25     for(int i=n-1;i>=0;i--){
26         int A=sum[s1[i]-'A'],B=sum[s2[i]-'A'],C=sum[s3[i]-'A'];
27         if((A+B+x)%n!=C) return 0;
28         x=(A+B+x)/n;
29     }
30     return 1;
31 }
32 void search(int x){//当前匹配到第x个字母的数字
33     if(!cut()) return;
34     if(x==n){
35         if(pd()) print();
36         return;
37     }
38     for(int i=n-1;i>=0;i--){
39         if(used[i]) continue;//如果这个数字已经和某个字母匹配过就跳过
40         used[i]=1;
41         sum[wait[x]]=i;
42         search(x+1);//继续匹配下一个字母
43         used[i]=0;
44         sum[wait[x]]=-1;//回溯
45     }
46     return;
47 }
48 int num=0;
49 void get(int x){
50     if(used[x]==0){
51         used[x]=1;
52         wait[num++]=x;//把需要对应数字的字母找出来记录好
53         return;
54     }
55 }
56 int main(){
57     freopen("alpha.in","r",stdin);
58     freopen("alpha.out","w",stdout);
59     cin>>n;
60     memset(sum,-1,sizeof(sum));
61     scanf("%s",s1);
62     scanf("%s",s2);
63     scanf("%s",s3);
64     for(int i=n-1;i>=0;i--){
65         get(s1[i]-'A');
66         get(s2[i]-'A');
67         get(s3[i]-'A');
68     }
69     memset(used,0,sizeof(used));//标记清零
70     search(0);
71     return 0;
72 }
代码戳这里
原文地址:https://www.cnblogs.com/THWZF/p/11760893.html