• 【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
    %d
    %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值进去计算比较即可。然而我并不会这第一步啊......

  • 相关阅读:
    leetcode 337. House Robber III
    leetcode 366 Find Leaves of Binary Tree
    leetcode 250 Count Univalue Subtrees
    leetcode 132 Palindrome Pairs 2
    leetcode 131 Palindrome Pairs
    leetcode 336 Palindrome Pairs
    leetcode 214 Shortest Palindrome
    leetcode 9 Palindrome Number
    Socket编程
    Zookeeper
  • 原文地址:https://www.cnblogs.com/JKAI/p/7289407.html
Copyright © 2020-2023  润新知