问题描述:二维背包,求达到经验值时耐心的最小消耗,当包内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; }