• NOIP2010 提高组合集


    NOIP 2010 提高组合集

    T1 机器翻译

    模拟题,用一个栈模拟,桶记录即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #define N 1010 
    using namespace std; map<int,int>mp; int que[N],a[N]; int l,r;
    int main()
    {
        int ans=0;
        int m,n; scanf("%d%d",&m,&n); for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(mp[a[i]]) continue;
            else
            {
                ans++;
                que[++r]=a[i];
                mp[a[i]]=1;
                if(r-l+1>m)
                {
                    mp[que[l]]=0;
                    l++;
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    T2 关押罪犯

    开始的时候这个题特别容易做成直接模拟,然后记录带敌人集合并查集的最大值之类的错误做法。

    这个题我们将所有的关系按照怨气值排序,紧接着我们只要逐一尽量满足即可。第一个不能满足的就是答案。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    struct Node {int x,y,z;}f[100010];
    int n,m,a[20005],b[20005],i;
    inline bool cmp(const Node &x,const Node &y) {return x.z>y.z;}
    int find(int x) {return a[x]==x?x:a[x]=find(a[x]);}
    inline void merge(int x,int y) {a[find(x)]=find(y);}
    inline bool check(int x,int y) {return find(x)==find(y);}
    int main()
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++) a[i]=i;
        for(i=1;i<=m;i++)
            scanf("%d%d%d",&f[i].x,&f[i].y,&f[i].z);
        sort(f+1,f+m+1,cmp);
        for(i=1;i<=m+1;i++)
        {
            if(check(f[i].x,f[i].y)) {printf("%d",f[i].z);break;}
            else
            {
                if(!b[f[i].x]) b[f[i].x]=f[i].y;
                    else {merge(b[f[i].x],f[i].y);}
                if(!b[f[i].y]) b[f[i].y]=f[i].x;
                    else {merge(b[f[i].y],f[i].x);}
            }
        }
        return 0;
    }
    

    T3 乌龟棋

    一眼dp的题。关键在于状态,开始的时候我设成了f[all][i][j][k][l],表示一共走了all,每个卡片分别用了i,j,k,l个。然后自信的认为最后一维可以卡掉,然后就不会优化了。

    之后开心的开题解,以为对于那个东西可以有什么好的方式优化,结果... ...tm我们可以把第一维压掉...转移显然。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std; int num[400];
    int f[41][41][41][41]; int g[5];
    inline void fix(int &x,int y) {x=max(x,y);}
    int main()
    {
        int n,m,x; cin >> n >> m ;
        for(int i=1;i<=n;i++) scanf("%d",&num[i]);
        for(int i=1;i<=m;i++) scanf("%d",&x),g[x]++;
        f[0][0][0][0]=num[1];
        for(int i=0;i<=g[1];i++) for(int j=0;j<=g[2];j++) for(int k=0;k<=g[3];k++) for(int l=0;l<=g[4];l++)
        {
            int dic=i+2*j+3*k+4*l+1;
            if(i) fix(f[i][j][k][l],f[i-1][j][k][l]+num[dic]);
            if(j) fix(f[i][j][k][l],f[i][j-1][k][l]+num[dic]);
            if(k) fix(f[i][j][k][l],f[i][j][k-1][l]+num[dic]);
            if(l) fix(f[i][j][k][l],f[i][j][k][l-1]+num[dic]);
        }
        printf("%d
    ",f[g[1]][g[2]][g[3]][g[4]]);
        return 0;
    }
    

    T4 引水入城。

    联赛中还算友好的爆搜。我们对于每一个接受格子开始bfs,易于发现每个发射格子能匹配的肯定是一条线段,之后dp就行了。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 510
    #define nx x+xx[i]
    #define ny y+yy[i]
    int l[N][N],r[N][N];
    int high[N][N];
    int n,m;
    bool vis[N][N];
    int xx[4]={-1,0,1,0};
    int yy[4]={0,1,0,-1};
    int qx[N*N],qy[N*N];
    inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
    int rd() {int x=0; char c=0; while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
    void dfs(int x,int y)
    {
        vis[x][y]=true;
        for(int i=0;i<4;i++)
        {
            if(nx<1 || nx>n || ny<1 || ny>m) continue;
            if(high[nx][ny]>=high[x][y]) continue;
            if(!vis[nx][ny])dfs(nx,ny);
            l[x][y]=min(l[x][y],l[nx][ny]);
            r[x][y]=max(r[x][y],r[nx][ny]);
        }
    }
    int main()
    {
        n=rd(),m=rd(); memset(l,0x7f,sizeof l);
        for(int i=1;i<=m;i++) l[n][i]=r[n][i]=i;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) high[i][j]=rd();
        for(int i=1;i<=m;i++) if(!vis[1][i]) dfs(1,i);
        bool flag=false;
        int cnt=0;
        for(int i=1;i<=m;i++) 
        {   
            if(!vis[n][i])
            {
                flag=true;
                cnt++;
            }
        }
        if(flag)
        {
            puts("0");
            printf("%d",cnt);
            return 0;
        }
        int left=1;
        while(left<=m)
        {
            int maxr=0;
            for(int i=1;i<=m;i++) if(l[1][i]<=left) maxr=max(maxr,r[1][i]);
            cnt++;
            left=maxr+1;
        }
        puts("1");
        printf("%d",cnt);
    }
    
  • 相关阅读:
    CentOS8下安装mysql8
    Git使用
    《操作系统导论》读书笔记
    《Linux命令行大全》读书笔记
    Centos8 开机后显示 Activate the web console with: systemctl enable --now cockpit.socke
    numpy学习笔记
    CentOS8使用阿里源
    Python 面向对象
    matplotlib解决不显示中文问题
    MySQL基础第三课
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9588959.html
Copyright © 2020-2023  润新知