HDU 2159二维背包

问题描述:二维背包,求达到经验值时耐心的最小消耗,当包内worth达到规定值时跳出返回答案。

 

关于三层循环的顺序:(i:物品种类,c1:cost1,c2,cost2)

1、

for i = 1 to k
    for c1 = 1 to c1_max
        for c2 = 1 to c2_max

用每种物品进行更新状态,只有在循环结束时才能得到最优解;每次外层循环++时,某状态下第i种物品使用数便可以确定了,故便于记录第i种物品在某状态中用了多少个。

2、

for c1 =1 to c1_max
    for c2 = 1 to c2_max
        for i = 1 to k

这样是对每种状态进行更新,i 循环一圈以后bag[c1][c2]完成更新,得到的就是该状态下的最优解;通过调整循环c1 c2的先后顺序方便求出确定worth下某种代价的最小消耗。

 

这题是确定worth(经验值)求最小cost(耐心)消耗,故采用第二种。用第一种也能求解但比较麻烦而且有额外的时间开销。

代码如下:

#include<stdio.h>
#include<string.h>

int bag[105][105],cost[105],worth[105];

int max(int a,int b)
{
    return a>b?a:b;
}

int main()
{
    int n,m,k,s,i,j,a,b,flag;
    while(~scanf("%d%d%d%d",&n,&m,&k,&s))
    {
        for(i=0;i<k;i++)
            scanf("%d%d",&worth[i],&cost[i]);
        memset(bag,0,sizeof(bag));
        flag=0;
        for(j=1;j<=m;j++)
        {
            for(a=1;a<=s;a++)
            {
                for(i=0;i<k;i++)
                {
                    if(j>=cost[i])
                        bag[j][a]=max(bag[j-cost[i]][a-1]+worth[i],bag[j][a]);
                }
                if(bag[j][a]>=n)
                {
                    flag=j;
                    goto mark;
                }
            }
        }
        mark:
        if(flag)
            printf("%d\n",m-flag);
        else
            printf("-1\n");
    }
        return 0;
}
posted @ 2014-03-04 15:43  zhen94  阅读(170)  评论(0编辑  收藏  举报