• CSU 1326: The contest(分组背包)


    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1326

    题意:

          n个题目,每个题目都有一个价值Pi和相对能力消耗Wi,但是有些题目因为太坑不能同时做出来,并且坑题具有传递性。(a和b一起做会坑、b和c会坑则a和c也会坑) 它们最多可以作出多少价值的题目。

    分析:先用并查集,将组分出来,然后进行分组背包

       注意F数组,数组开辟的大小应该为总价值的最大值,还有初始化别忘记了  

       以及j-pi[i]>=0
    一维数组:

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define LL long long
    const int MOD=1000000007;
    const int MN=1010;
    int father[MN];
    int num[MN][MN];
    int rank[MN];
    int f[MN];
    int val[MN],pi[MN];
    int vis[MN];
    int cnt[MN];
     
    void Make_set(int n)
    {
        for(int i=0; i<=n; i++)
        {
            father[i]=i;
        }
    }
     
    int Find(int x)
    {
        if(x!=father[x])
            father[x]=Find(father[x]);
        return father[x];
    }
     
    void Union(int x,int y)
    {
        if(x==y) return ;
        father[x]=y;
    }
     
    int main()
    {
        int i,j,k,n,m;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            Make_set(n);
            for(i=1; i<=n; i++)
            {
                scanf("%d%d",&val[i],&pi[i]);
            }
            int a,b;
            for(i=1; i<=k; i++)
            {
                scanf("%d%d",&a,&b);
                int x=Find(a);
                int y=Find(b);
                Union(x,y);
            }
            memset(vis,0,sizeof(vis));
            for(i=1; i<=n; i++)
            {
                int t=Find(i);
                vis[t]++;
            }
            int cas=0;
            for(i=1; i<=n; i++)
            {
                if(vis[i])
                {
                    ++cas;
                    int tes=0;
                    for(j=1; j<=n; j++)
                    {
                        if(father[j]==i)
                            num[cas][++tes]=j;
                    }
                    cnt[cas]=vis[i];
                }
            }
            memset(f,0,sizeof(f));
            for(i=1;i<=cas;i++)
            {
                for(j=m;j>=0;j--)
                {
                    for(k=1;k<=cnt[i];k++)
                    {
                        int xx=num[i][k];
                        if(j-pi[xx]>=0) f[j]=max(f[j],f[j-pi[xx]]+val[xx]);
                    }
                }
            }
            printf("%d
    ",f[m]);
        }
        return 0;
    }
    View Code

    二维数组:

    循环取最大值的那里要小心,始终要和f[i-1][j]进行比较

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define LL long long
    const int MOD=1000000007;
    const int MN=1010;
    int father[MN];
    int num[MN][MN];
    int rank[MN];
    int f[MN][MN];
    int val[MN],pi[MN];
    int vis[MN];
    int cnt[MN];
     
    void Make_set(int n)
    {
        for(int i=0; i<=n; i++)
        {
            father[i]=i;
        }
    }
     
    int Find(int x)
    {
        if(x!=father[x])
            father[x]=Find(father[x]);
        return father[x];
    }
     
    void Union(int x,int y)
    {
        if(x==y) return ;
        father[x]=y;
    }
     
    int main()
    {
        int i,j,k,n,m;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            Make_set(n);
            for(i=1; i<=n; i++)
            {
                scanf("%d%d",&val[i],&pi[i]);
            }
            int a,b;
            for(i=1; i<=k; i++)
            {
                scanf("%d%d",&a,&b);
                int x=Find(a);
                int y=Find(b);
                Union(x,y);
            }
            memset(vis,0,sizeof(vis));
            for(i=1; i<=n; i++)
            {
                int t=Find(i);
                vis[t]++;
            }
            int cas=0;
            for(i=1; i<=n; i++)
            {
                if(vis[i])
                {
                    ++cas;
                    int tes=0;
                    for(j=1; j<=n; j++)
                    {
                        if(father[j]==i)
                            num[cas][++tes]=j;
                    }
                    cnt[cas]=vis[i];
                }
            }
            memset(f,0,sizeof(f));
            for(i=1;i<=cas;i++)
            {
                for(j=m;j>=0;j--)
                {
                    for(k=1;k<=cnt[i];k++)
                    {
                        int xx=num[i][k];
                        if(j-pi[xx]>=0)
                        {
                            f[i][j]=max(f[i][j],f[i-1][j-pi[xx]]+val[xx]);
                            f[i][j]=max(f[i-1][j],f[i][j]);
                        }
                        else f[i][j]=max(f[i][j],f[i-1][j]);
                    }
                }
            }
            printf("%d
    ",f[cas][m]);
        }
        return 0;
    }
    View Code

    分组背包:http://www.nocow.cn/index.php/%E5%88%86%E7%BB%84%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98

  • 相关阅读:
    Select loop
    shell学习
    硬链接与软连接的区别_(转)
    Windows 远程桌面连接Ubuntu16.04图像界面
    C# mysql 连接Apache Doris
    Hadoop 2.7.3 分布式集群安装
    ubuntu 16.04安装Chrome离线crx插件包
    RPC框架之Thrift分析(转)
    ubuntu 16.04安装ibus中文输入法
    secureCRT下linux rz命令上传文件失败或变小(破损)的问题解决方法
  • 原文地址:https://www.cnblogs.com/zsboy/p/3349920.html
Copyright © 2020-2023  润新知