HDU 1712 ACboy needs your helpss - 分组背包+最多那一个

/*
    http://acm.hdu.edu.cn/showproblem.php?pid=1712  ACboy needs your helpss
	分组背包 每组最多拿一个 ,一定要注意初始化,当前需要循环的初始化为上一次的结果,才能保证全局最优解
	这题目卡cin,数据太多了,让我超时了一次
	另外这题目还有一个办法,改变循环顺序也可使得每组至多拿一个物品
*/

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#define CLR(c,v) (memset(c,v,sizeof(c)))
using namespace std;

template <typename _T>
inline _T Max(_T a,_T b){
	return (a>b)?(a):(b);
}
template <typename _T>
inline _T Max(_T a,_T b,_T c){
	return (a>Max(b,c))?(a):(Max(b,c));
}

const int inf     =  -(1<<30);
const int INF     =   (1<<30);
const int SET     =  100 + 2; 
const int COST    =  1e2 + 2; // 一消耗 时间限制

int dp[SET][COST];

int main(){
	freopen("Input.txt","r",stdin);
	freopen("out.txt","w",stdout);
	int n_set, max_cost;
	while(cin >> n_set >> max_cost && (n_set || max_cost)){
		CLR(dp,0);
		for (int i = 1 ; i <= n_set ; i++){ // foreach set
			for (int t = 0 ; t <= max_cost ; t++) 
                dp[i][t] = dp[i-1][t]; // 为了保证全局最优解,初始化为上一次结果  
			for (int j = 1 ; j <= max_cost ; j++){// foreach cost1
				int value;
				scanf("%d",&value);
				int c1 = j;
				int c2 = 1;
				for (int t = max_cost ; t >= c1 ; t--){ // foreach cost1
					dp[i][t] = Max(dp[i][t], dp[i-1][t-c1] + value); 
					// 这种循环不是由二维费用演变过来的,					
					// 当这里改成二维费用的话则表示全局仅拿一个的情况,
					// 必须将初始化修改为拿0个的为上一次拿一个的最优值才行
					// 而是每次 当前值 仅跟 最初始状态+now_value比较,取最大值
				}
			}
		}
		cout << dp[n_set][max_cost] << endl;
	}
	return 0;
}

你可能感兴趣的:(C++)