题目大意:见lrj紫书205页,习题9-5,这题目做的真的很爽,刚开始用暴力递归,然后想了一下用dp去做了,真正的对递归和dp的内在联系有了一个稍微的了解。主要思路还是用dp[i][j]表示在加入i件物品费用j是否存在,然后dp完了之后在搜索一遍就ok。
题目链接:https://vjudge.net/problem/UVA-242
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;
const int maxn = 12;
int n , setn , s;
bool dp[maxn][1005];
int log[maxn];
vector<int> set[maxn];
int maxcover () {
for (int i = 0 ; ; i++) {
int flag = 0;
for (int j = 0 ; j <= s ; j++) {
if (dp[j][i]) {
flag = 1;
break;
}
}
if (!flag)
return i-1;
}
}
int solve (int index) {
dp[0][0] = 1;
for (int i = 1 ; i <= s ; i++) {
for (int j = 0 ; j <= log[i-1] ; j++) {
for (int k = 0 ; k < n ; k++) {
if (dp[i-1][j]) {
dp[i][j+set[index][k]] = 1;
log[i] = max(log[i] , j+set[index][k]);
}
}
}
}
return maxcover();
}
int compare (int a , int b) {
if(set[a].size() < set[b].size()) return a;
if(set[a].size() > set[b].size()) return b;
for (int i = set[a].size()-1 ; i >= 0 ; i--) {
if (set[a][i] < set[b][i]) return a;
if (set[a][i] > set[b][i]) return b;
}
return a;
}
int main () {
while (scanf("%d%d" , &s , &setn) && s) {
for (int i = 0 ; i < maxn ; i++) set[i].clear();
int ans = -1;
int index = 0;
for (int i = 0 ; i < setn ; i++) {
scanf("%d" , &n);
for (int j = 0 ; j < n ; j++) {
int tmp;
cin >> tmp;
set[i].push_back(tmp);
}
memset(dp,0,sizeof(dp));
memset(log,0,sizeof(0));
int tmp = solve(i);
if(ans <= tmp) {
if (ans < tmp)
index = i;
else
index = compare(index , i);
ans = tmp;
}
}
printf("max coverage =%4d :" , ans);
for (int j = 0 ; j < set[index].size() ; j++)
printf("%3d" , set[index][j]);
cout << endl;
}
}
网上搜索了一个别人更加优秀的解题报告,今天先睡了,来日更新一下,自叹不如!