【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;
}
T1

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;
}
T2

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;
}
T3

T4等价表达式

题目链接

这道题真 不想写(懒),yyl说这个以后应该不会考,所以留个坑?

只需要把字符串转化成算式之后在代几个a值进去计算比较即可。然而我并不会这第一步啊......

posted @ 2017-08-05 10:43  Child-Single  阅读(320)  评论(0编辑  收藏  举报