【NOIP2005】提高组
T1谁拿了最多奖学金
没什么好说的,日常签到题,模拟即可。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int main() { int n,maxn=0,de=0,s=0,a1,a2,a3,x=1; char name[102][22],xi,xue; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s %d %d %c %c %d",name[i],&a1,&a2,&xue,&xi,&a3); de=0; if(a1>80&&a3)de+=8000; if(a1>85&&a2>80)de+=4000; if(a1>90)de+=2000; if(a1>85&&xi=='Y')de+=1000; if(a2>80&&xue=='Y')de+=850; s+=de; if(de>maxn){maxn=de;x=i;} } printf("%s\n%d\n%d",name[x],maxn,s); return 0; }
T2过河
其实如果独木桥的长度短一点的话很好做,直接dp即可。但是长度L达到1e9,这样做显然会MLE。所以我们得做一些优化。可以发现石子的数量最多只有100个,因此中间必然有大片的地方是没有石子的,而这也是导致我们浪费大量空间的原因。
所以我们可以进行路径压缩,因为0<s<t<=10(当s==t时直接输出位置能被s整除的石子数即可),而10以内的两个数的最小公倍数都小于或等于90。因此我们可以把两个石子之间的距离都取余90,因此这片区域是可以直接跳过的。剩下的就可以直接dp了。
dp的详细细节看代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int a[10000]={0},f[10000],sz[10000]={0}; int main() { int l,s,t,m; memset(f,127,sizeof(f)); scanf("%d %d %d %d",&l,&s,&t,&m); for(int i=1;i<=m;i++)scanf("%d",&a[i]); a[m+1]=l; if(s==t) { int ans=0; for(int i=1;i<=m;i++)if(a[i]%s==0)ans++; printf("%d",ans); return 0; } sort(a,a+1+m); for(int i=0;i<=m;i++)a[i+1]=a[i]+(a[i+1]-a[i])%90; for(int i=1;i<=m;i++)sz[a[i]]=1; for(int i=s;i<=t;i++){if(sz[i])f[i]=1;else f[i]=0;} for(int i=s+1;i<=a[m+1]+t-1;i++) { for(int j=s;j<=t;j++) { if(j>i)break; f[i]=min(f[i-j],f[i]); } if(sz[i])f[i]++; } for(int i=a[m+1]+1;i<=a[m+1]+t-1;i++)f[a[m+1]]=min(f[a[m+1]],f[i]); printf("%d",f[a[m+1]]); return 0; }
T3篝火晚会
这道题,如果要把当前环变成目标环,最小代价的策略肯定是动尽量少的点。我们应该注意到,每个人最多应该只会动一次,动完这一次就会在他应该在的地方,因此平均下来每个人移动所需的代价就是1,我们只需要算出不需要动的人数的最大值,用总人数减去这个最大值即为答案。然而本题最难的一个地方在于,这是一个环,因此起始位置、方向都是不确定的。所以我们要求出与目标位置距离相同的人数,求其最大值。因为是环,还要反过来算一次(这里最难理解,要好好想一想!)。
代码很简单,重在理解做环这类问题时所应该注意的一些问题。
#include<cstdio> #include<cstring> #include<iostream> const int M=50005; using namespace std; int c[M],ai[M],bi[M],vis[M]; int m1[M],m2[M]; int read() { int ans=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} return ans*f; } int main() { int n=read(),ans=0; for(int i=1;i<=n;i++) ai[i]=read(),bi[i]=read(); c[1]=1;c[2]=ai[1];vis[1]=vis[c[2]]=1; for(int i=2;i<n;i++) { if(c[i-1]==ai[c[i]])c[i+1]=bi[c[i]]; else if(c[i-1]==bi[c[i]])c[i+1]=ai[c[i]]; else {printf("-1");return 0;} vis[c[i+1]]=1; } for(int i=1;i<=n;i++) if(!vis[i]){printf("-1");return 0;} for(int i=1;i<=n;i++) { int t=(c[i]-i+n)%n; m1[t]++; ans=max(ans,m1[t]); t=(c[n-i+1]-i+n)%n; m2[t]++; ans=max(ans,m2[t]); } printf("%d",n-ans); return 0; }
T4等价表达式
这道题真 不想写(懒),yyl说这个以后应该不会考,所以留个坑?
只需要把字符串转化成算式之后在代几个a值进去计算比较即可。然而我并不会这第一步啊......