• USACO 2016 February Contest, Gold解题报告


    1.Circular Barn 

     http://www.usaco.org/index.php?page=viewproblem2&cpid=621

    贪心

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    long long sum(long long v) 
    {
      return v*(v+1)*(2*v+1)/6;
    }
    int main() 
    {
          int N,c=0;
          scanf("%d",&N);
          vector<long long> A(N);
          for(int i=0;i<N;i++) 
        {
            scanf("%d",&A[i]);
            c=max(0ll,c+A[i]-1);
          }
          for(int i=0;;i++) 
        {
            if(c==0) 
            {
                  rotate(A.begin(),A.begin()+i,A.begin()+N);
                  break;
            }
            c=max(0ll,c+A[i]-1);
          }
          long long res=0;
          for (int i=0;i<N;i++) 
        {
            res+=sum(A[i]+c-1)-sum(c-1);
            c=max(0ll,c+A[i]-1);
          }
          printf("%d",res);
    }

    2.Circular Barn Revisited

    http://www.usaco.org/index.php?page=viewproblem2&cpid=622

    首先,记录从i开始的j个房间的奶牛都从i从i号门进入所走的总距离。

    然后进行dp,找出最小路程

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 100
    #define MAXK 7
    int n,r[MAXN+10],k;
    long long f[MAXN*2+1][MAXN+1][MAXK+1],ans=0x7fffffffffffffffll,dist[MAXN+10][MAXN+10];
    void Read(int &x){
        char c;
        while(c=getchar(),c!=EOF)
            if(c>='0'&&c<='9'){
                x=c-'0';
                while(c=getchar(),c>='0'&&c<='9')
                    x=x*10+c-'0';
                ungetc(c,stdin);
                return;
            }
    }
    void read(){
        Read(n),Read(k);
        int i;
        for(i=1;i<=n;i++)
            Read(r[i]);
    }
    void prepare(){
        int i,j;
        for(i=1;i<=n;i++){
            dist[i][1]=0;
            for(j=2;j<=n;j++)
                dist[i][j]=r[(i+j-2)%n+1]*(j-1)+dist[i][j-1];
        }
    }
    void dp(){
        int i,j,l,t=2*n,p;
        memset(f,0x3f,sizeof f);
        for(i=0;i<=t;i++)
            f[i][0][0]=0;
        for(i=1;i<=n;i++){
            for(j=1;j<=n&&j<=i;j++)
                for(l=1;l<=k;l++)
                    for(p=1;p<=j;p++)
                        f[i][j][l]=min(f[i][j][l],f[i-p][j-p][l-1]+dist[i-p+1][p]);
            ans=min(ans,f[i][n][k]);
        }
        for(i=n+1;i<=t;i++){
            for(j=1;j<=n;j++)
                for(l=1;l<=k;l++)
                    for(p=1;p<=j;p++)
                        f[i][j][l]=min(f[i][j][l],f[i-p][j-p][l-1]+dist[(i-p)%n+1][p]);
            ans=min(ans,f[i][n][k]);
        }
    }
    int main()
    {
        read();
        prepare();
        dp();
        printf("%lld
    ",ans);
    }

    3.Fenced In

    最小生成树

    处理出连通块之间栅栏的长度然后做最小生成树即可。 但是这样会T,尽管算法时间复杂度为 O(n2log2n) 

    优化:由于每一行或每一列中的相邻两个连通块之间的栅栏长度相等,我们可以考虑使用kruskal算法,仅仅对每两个栅栏之间的距离排序,然后然后再对这一行(列)的所有相邻连通块连边即可。 

    #include<cstdio>
    #include<algorithm>
    #define MAXN 2000
    using namespace std;
    long long ans;
    int n,a[MAXN+10],b[MAXN+10],A,B,m,tot,fa[(MAXN+1)*(MAXN+1)+10];
    void Read(int &x){
        char c;
        while(c=getchar(),c!=EOF)
            if(c>='0'&&c<='9'){
                x=c-'0';
                while(c=getchar(),c>='0'&&c<='9')
                    x=x*10+c-'0';
                ungetc(c,stdin);
                return;
            }
    }
    void read(){
        int i,t;
        Read(A),Read(B),Read(n),Read(m);
        for(i=1;i<=n;i++)
            Read(a[i]);
        for(i=1;i<=m;i++)
            Read(b[i]);
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        a[++n]=A;
        b[++m]=B;
        for(i=n;i;i--)
            a[i]-=a[i-1];
        for(i=m;i;i--)
            b[i]-=b[i-1];
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        t=n*m;
        for(i=1;i<=t;i++)
            fa[i]=i;
    }
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    void kruskal(){
        int i,j,k,l;
        i=j=1;
        while(i<=n||j<=m){
            if(j>m||(i<=n&&a[i]<=b[j])){
                k=(i-1)*m+1;
                for(l=1;l<m;l++,k++)
                    if(find(k)!=find(k+1))
                        fa[fa[k]]=fa[k+1],ans+=a[i];
                ++i;
            }
            else{
                k=j;
                for(l=1;l<n;l++,k+=m)
                    if(find(k)!=find(k+m))
                        fa[fa[k]]=fa[k+m],ans+=b[j];
                ++j;
            }
        }
    }
    int main()
    {
        read();
        kruskal();
        printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    linux安装mysql
    yum命令
    java启动jar包中的指定类
    linux系统配置参数修改
    iconfont阿里巴巴矢量图标库批量保存
    Python 使用Pandas读取Excel的学习笔记
    在Ubuntu18.04的Docker中安装Oracle镜像及简单使用
    Eclipse 安装PyDev开发Python及初步使用
    Python打包工具
    MacOS下打包Python应用
  • 原文地址:https://www.cnblogs.com/wisdom-jie/p/9302723.html
Copyright © 2020-2023  润新知