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\n",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\n",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

你可能感兴趣的:(test)