【NOIP2004】提高组
T1津津的储蓄计划
签到题,直接模拟:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int main() { int ans=0,now=0,ai[15],a; for(int i=1;i<=12;i++)scanf("%d",&ai[i]); for(int i=1;i<=12;i++) { a=ai[i]; now+=300; if(now<a){printf("-%d",i);return 0;} int x=(now-a)/100*100; ans+=x;now-=x+a; } printf("%d",now+ans+(ans/5)); return 0; }
T2合并果子
优先队列(小根堆)直接贪心搞定:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; struct node{ int w; bool operator<(const node&x)const{return w>x.w;} }; priority_queue<node>q; int main() { int n,a,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&a),q.push((node){a}); for(int i=1;i<=n-1;i++) { node x1=q.top(); q.pop();node x2=q.top();q.pop(); ans+=x1.w+x2.w;q.push((node){x1.w+x2.w}); }printf("%d",ans); return 0; }
T3合唱队形
枚举每个点为中心,求出从左端和从右端的最长上升子序列长度之和,储存其最大值,再用总人数减去这个最大值即为答案:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<queue> using namespace std; int main() { int n,ti[105],f[105],f1[105],mxa=0,x; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&ti[i]),f[i]=f1[i]=1; for(int i=1;i<=n;i++) { for(int j=i-1;j>=1;j--) if(ti[i]>ti[j])f[i]=max(f[i],f[j]+1); } for(int i=n;i>=1;i--) { for(int j=i+1;j<=n;j++) if(ti[i]>ti[j])f1[i]=max(f1[i],f1[j]+1); } for(int i=1;i<=n;i++) { x=f[i]+f1[i]-1; mxa=max(mxa,x); } printf("%d",n-mxa); return 0; }
T4虫食算
本届NOIP提高组唯一有难度的题目,加剪枝的DFS即可解决,具体题解
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> const int maxn=36; using namespace std; char a[maxn],b[maxn],c[maxn],n; int ans[200],q[maxn]; bool used[maxn]; bool ok(int x,int jin) { if(ans[a[0]]+ans[b[0]]>=n)return 0; int i,j,k; for(i=x;i>=0;i--) { if(ans[a[i]]!=-1&&ans[b[i]]!=-1) { j=ans[a[i]]+ans[b[i]]+jin;jin=j/n; if(ans[c[i]]!=-1&&ans[c[i]]!=(j%n))return 0; if(ans[c[i]]==-1) { if(used[j%n])return 0; ans[c[i]]=j%n;used[j%n]=1;q[++q[0]]=c[i]; } } else break; } if(ans[a[0]]+ans[b[0]]>=n)return 0; for(;i>=0;i--) { if(ans[a[i]]!=-1&&ans[b[i]]!=-1) { j=ans[a[i]]+ans[b[i]]; if(ans[c[i]]!=-1&&ans[c[i]]!=(j%n)&&ans[c[i]]!=((j+1)%n))return 0; if(ans[c[i]]==-1&&used[j%n]&&used[(j+1)%n])return 0;continue; } if(ans[a[i]]!=-1&&ans[c[i]]!=-1) { j=ans[c[i]]-ans[a[i]]+n; if(used[j%n]&&used[(j-1)%n])return 0; } if(ans[b[i]]!=-1&&ans[c[i]]!=-1) { j=ans[c[i]]-ans[b[i]]+n; if(used[j%n]&&used[(j-1)%n])return 0; } } return 1; } bool dfs(int x,int jin,bool flag) { if(x<0)return 1; int p=q[0],i; if(flag) { if(ans[a[x]]!=-1)return dfs(x,jin,0); for(ans[a[x]]=n-1;ans[a[x]]>=0;ans[a[x]]--) { if(!used[ans[a[x]]]) { used[ans[a[x]]]=1; if(ok(x,jin)&&dfs(x,jin,0))return 1; while(q[0]>p) { used[ans[q[q[0]]]]=0;ans[q[q[0]]]=-1; q[0]--; } used[ans[a[x]]]=0; } } return 0; } if(ans[b[x]]!=-1)return dfs(x-1,(ans[a[x]]+ans[b[x]]+jin)/n,1); for(ans[b[x]]=n-1;ans[b[x]]>=0;ans[b[x]]--) { if(!used[ans[b[x]]]) { used[ans[b[x]]]=1; if(ok(x,jin)&&dfs(x-1,(ans[a[x]]+ans[b[x]]+jin)/n,1))return 1; while(q[0]>p) { int k=q[q[0]];used[ans[k]]=0;ans[k]=-1;q[0]--; } used[ans[b[x]]]=0; } } return 0; } int main() { scanf("%d",&n); scanf("%s",a); scanf("%s",b); scanf("%s",c); for(int i=0;i<n;i++)ans['A'+i]=-1; memset(used,0,sizeof(used)); dfs(n-1,0,1); printf("%d",ans['A']); for(int i=1;i<n;i++)printf(" %d",ans['A'+i]); return 0; } noip2004虫食算