目录
•$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 }
$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 }