动态规划--至少取一个的分组背包--hdu3033 I love sneakers!

来源:互联网 发布:吕思勉 知乎 编辑:程序博客网 时间:2024/06/15 07:35

n个物品,m元钱,k种种类。

求每个种类至少取一个物品,所能得到的最大价值。


分类里互斥的分组背包,每种类别最多取一个。

for all 组k

for u = V to 0

for i 属于k

dp[ k ][ u ] = max( dp[ k - 1 ][ u ], dp[ k ][ u - c[ i ] ] + v[ i ]);//k - 1这项说明对于k组的物品可以一个都不取,直接转移到第k类。

1.空间可以简化为一维,for ... for ... for ....dp[ u ] = max( dp[ u ], dp[ u - c[ i ] ] + v[ i ]);

2.递推中,先考虑容量u,再考虑物品i,所以在计算时,状态转移,就是每组的物品之间排斥,求max,要么取1个,要么不取。


而至少取一个的分组背包

for all 组k

for i 属于 k

for u = V to 0

if dp[ k - 1][ u - c[ i ] ] + v[ i ] >= 0//dp初始化为-1,表示状态无效,即有一组一个都选不了

dp[ k ][ u ] = max( dp[ k ][ u ],dp[ k - 1][ u - c[ i ] ] + v[ i ] );//由上一组转移来,则第k组必选

if dp[ k ][ u - c[ i ] ] + v[ i ] >= 0

dp[ k ][ u ] = max( dp[ k ][ u ],dp[ k ][ u - c[ i ] ] + v[ i ] );//由同一组转移来,则第k组可以多选

1.不能简化为一维,且最终答案在dp[ k ]里求max

2.递推中,先考虑物品,再考虑容量,在计算时,就是,先尽可能地放物品i,至放不下,就开始放物品i + 1,物品i + 1放入已放了物品i的背包,是相加相容的关系。


#include <iostream>

#include <vector>

#include <map>

#include <cstring>

#include <algorithm>

using namespacestd;

const int maxn =100 +5;

const int maxk =10 +5;

const int maxm =10000 +5;

const int INF =1 <<30;


struct snk{

    int a,b,c;

}sk[maxn];

int dp[maxk][maxm];

vector<int> gp[maxk];

int main()

{

    int n,m,k;

while(scanf("%d%d%d",&n,&m,&k) !=EOF)

{

   for (int i =1; i <= k; i ++) {

        gp[i].clear();

    }

    memset(dp,-1,sizeof(dp));


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

        scanf("%d%d%d",&sk[i].a,&sk[i].b,&sk[i].c);

        gp[sk[i].a].push_back(i);

    }

    int min_c =0;

    for (int i =1; i <= k; i ++) {

        int t =INF;

        for (int j =0; j <gp[i].size(); j ++) {

            t = min(t,sk[gp[i][j]].b);

        }

        min_c += t;

    }

    

    dp[0][0] =0;

    for (int i =1; i <= k ; i ++) {

            for (int j =0; j <gp[i].size(); j ++) {

                   for (int u = m; u >=sk[gp[i][j]].b; u --) {

                      

                    if(dp[i][u -sk[gp[i][j]].b] >=0)

                        dp[i][u] =max(dp[i][u],dp[i][u -sk[gp[i][j]].b] +sk[gp[i][j]].c);

                    if(dp[i -1][u -sk[gp[i][j]].b] >=0)

                           dp[i][u] =max(dp[i][u],dp[i -1][u - sk[gp[i][j]].b] + sk[gp[i][j]].c);

            }

        }

    }

    int max_v = *max_element(dp[k],dp[k] + m + 1) ;


    if (min_c > m) {

        printf("Impossible\n");

    }

    else printf("%d\n",max_v);

}

    return0;

}



阅读全文
0 0
原创粉丝点击