soj 2222 01背包变形

来源:互联网 发布:上海关键词优化 编辑:程序博客网 时间:2024/05/22 14:42

背景:wa~Tl~看来背包还是很欠缺啊~

思路1(1500ms):变形的01背包。把题目改为:选择一组HP和大于等于所需血量且这组物品的分数之和最小,即可。这里把HP看做cost,score看做weight。但是这个题有个特点是最后选择HP必须大于等于k,容易想到,最多我们会有k+10000(10000为单个物品的最大HP值)的HP值,所以我们有这样的转移方程:

for i 0....n

   for j K+10000....cost[i]

       F[j]=min(F[j],F[j-cost[i]]+weight[i]])

这实际上是通过最多多选不超过10000的HP来达到目的。

思路2(208ms):对01背包倒着走而多10000的计算而做出的优化。直接贴出方程,内容不难理解:

for i 0....n

   for j 0....k

       F[j+cost[i]]=min(F[j+cost[i]],F[j]+weight[i]])


思路1的代码:

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <vector>#include <map>#include <stack>#include <set>#include <iostream>using namespace std;const int M=1009,INF=0x3fffffff;int dp[1000000],c[10009][2];int main(void){    int t,HP,k,sum;    scanf("%d",&t);    while(t--){        sum=0;        scanf("%d%d",&HP,&k);        for(int i=0;i < 100000;i++) dp[i]=INF;        for(int i=0;i < k;i++){             scanf("%d%d",&c[i][0],&c[i][1]);             sum+=c[i][1];        }        dp[0]=0;        for(int i=0;i < k;i++){            for(int j=HP+10000;j >= c[i][0];j--){                dp[j]=min(dp[j],dp[j-c[i][0]]+c[i][1]);            }        }        int mins=INF;        for(int i=HP;i <= HP+10000;i++){            if(dp[i] < mins) mins=dp[i];        }        if(mins == INF ) printf("0\n");        else printf("%d\n",sum-mins);    }    return 0;}

0 0