分组背包题目

hdu 1712  ACboy needs your help 分组背包入门题目

http://acm.hdu.edu.cn/showproblem.php?pid=1712

题意:

acboy今年有n门课程,给出每门课程他授课多少天能获得的利润,w[i][j]表示第i个课程他如果授课j天可获得的利润,求在m天内它能够获得最大利润。

思路:
每门课程看做一个分组,每门课程对应着m个物品可选,直接套用分组背包即可。

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))

#define Min(a , b) ((a) < (b) ? (a) : (b))

#define Max(a , b) ((a) > (b) ? (a) : (b))



#define ll __int64

#define inf 0x7f7f7f7f

#define MOD 100000007

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define test puts("<------------------->")

#define maxn 100007

#define M 107

#define N 107

using namespace std;

//freopen("din.txt","r",stdin);



int f[N];

int w[N][N];



int main(){

   // freopen("din.txt","r",stdin);

    int i,j,k;

    int n,m;

    while (~scanf("%d%d",&n,&m)){

        if (!n && !m) break;

        for (i = 1; i <= n; ++i){

            for (j = 1; j <= m; ++j) scanf("%d",&w[i][j]);

        }

        CL(f,0);

        for (i = 1; i <= n; ++i){

            for (j = m; j >= 1; --j){

                for (k = 1; k <= j; ++k){//注意这里小于等于j

                    f[j] = max(f[j],f[j - k] + w[i][k]);

                }

            }

        }

        printf("%d\n",f[m]);

    }

    return 0;

}

 

hdu 3033 I love sneakers! 变形的分组背包(好题)

http://acm.hdu.edu.cn/showproblem.php?pid=3033

题意:

给出n个鞋子,每个鞋子分别对应着买它需要的费用,以及买完后获得的价值。这n个鞋子总共有m种品牌,保证每种品牌至少选择一个,求可能获得的最大价值。

思路:
这里保证每种品牌至少选择一个买了,所以才开始我利用num[i][j]表示到达i状态第j中品牌是否选了。而且也是空间优化到一维的结果超时了,算了算肯定超时。后来看了一下解题报告,才明白的。

首先f[i][j]表示选择了前i种商品,用了j的钱数所能得到的最大值,由于每种品牌至少选择一个所以只要把for循环变换一下即可保证能够多选某种品牌,但是这里怎么样保证由上一状态来的状态肯定选择了i-1呢,所以我们只需要dp[i - 1][j] != -1的因为这样的状态保证选择i-1这种状态,回想一下01背包的时候它会把-1覆盖成上一状态值,而这里不需要,还有这里c可能为0,我们必须首先保证最后计算由上一状态转移到该状态的值,否则如果先计算的话,就可能会造成一双鞋子买了多遍。。。

View Code
#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <queue>

#include <stack>

#include <set>

#include <map>

#include <string>



#define CL(a,num) memset((a),(num),sizeof(a))

#define iabs(x)  ((x) > 0 ? (x) : -(x))

#define Min(a , b) ((a) < (b) ? (a) : (b))

#define Max(a , b) ((a) > (b) ? (a) : (b))



#define ll __int64

#define inf 0x7f7f7f7f

#define MOD 100000007

#define lc l,m,rt<<1

#define rc m + 1,r,rt<<1|1

#define pi acos(-1.0)

#define test puts("<------------------->")

#define maxn 100007

#define M 10007

#define N 12

using namespace std;

//freopen("din.txt","r",stdin);



struct node{

    int c,w;

}tp;

int f[N][M];

vector<node>vc[N];



int Get(){

    char ch = getchar();

    while (ch < '0' || ch > '9') ch = getchar();

    int num = 0;

    while (ch >= '0' && ch <= '9'){

        num = num*10 + ch - '0';

        ch = getchar();

    }

    return num;

}

int main(){

    //freopen("din.txt","r",stdin);

    int i,j,k;

    int n,V,m;

    int a,b,c;

    while (~scanf("%d%d%d",&n,&V,&m)){

        for (i = 0; i <= m; ++i) vc[i].clear();

        for (i = 0; i < n; ++i){

            a = Get();

            b = Get();

            c = Get();

            tp.c = b; tp.w = c;

            vc[a].push_back(tp);//分类

        }

        for (i = 1; i <= m; ++i){

            for (j = 0; j <= V; ++j){

                f[i][j] = -1;

            }

        }

        for (i = 0; i <= V; ++i) f[0][i] = 0;//初始化



        for (i = 1; i <= m; ++i){

            int c,w;

            int len = vc[i].size();

            for (j = 0; j < len; ++j){

                 c = vc[i][j].c;

                 w = vc[i][j].w;

                for (k = V; k >= c; --k){

                   if (f[i][k - c] != -1)//必须先计算多选的情况

                   f[i][k] = max(f[i][k],f[i][k - c] + w);

                   if (f[i - 1][k - c] != -1)

                   f[i][k] = max(f[i][k],f[i - 1][k - c] + w);

                }

            }

        }

        if (f[m][V] == -1) puts("Impossible");

        else printf("%d\n",f[m][V]);



    }

    return 0;

}

 

待更新......

你可能感兴趣的:(分组)