POJ 1837

刚看完背包九讲就来做的这题,判断出是分组背包,一个砝码放在任意一个挂钩就是一个分组,其实就是比01背包多了一重循环,保证每个砝码只被放一次。陷入了分组背包的误区 错误地认为这题也和经典的背包问题一样是求最优方案或者最优方案总数。看了网上的题解才醒悟到具体问题要具体分析,从状态入手。这题是要得到恰好用完所有砝码并达到平衡态的方案数。而平衡态并不能通过找最优(即在状态转移中取较小或较大)来得到,因为不能保证在转移中取较大或较小就能使得最后一定能到达平衡态。

这里采用平衡度( ∑ 力 臂 )作为 dp d p 的第二维, dp[i][j] d p [ i ] [ j ] 表示挂上前 i i 个砝码得到平衡度j的方案数。这样可以得到平衡度任意取值时的方案数的状态表示,进而可以计算方案总数。平衡度最大值为15 * 20 * 25 = 7500,取值范围-7500~7500,可转化为0~15000,7500为平衡态。

转移方程为 dp[i][j+c[k]g[i]]=dp[i1][j] d p [ i ] [ j + c [ k ] ∗ g [ i ] ] = ∑ d p [ i − 1 ] [ j ]

#include<cstdio>

using namespace std;

int dp[25][15000];
int c[25];
int g[25];

int main(){
    int C,G;
    scanf("%d%d",&C,&G);
    for(int i = 1; i <= C; ++i) scanf("%d",&c[i]);
    for(int i = 1; i <= G; ++i) scanf("%d",&g[i]);
    dp[0][7500] = 1;
    for(int i = 1; i <= G; ++i){
        for(int j = 0; j <= 15000; ++j){
            if(dp[i-1][j]){
                for(int k = 1; k <= C; ++k){
                    dp[i][j + c[k]*g[i]] += dp[i-1][j];
                }
            }
        }
    }
    printf("%d\n",dp[G][7500]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值