題目描述:假定一張信封最多貼5張郵票,如果只能貼1分和3分的郵票,可以組成面值1~13以及 15,但不能組成面值14。我們說:對於郵票組合{1,3}以及數量上限S=5,最大連續郵資爲 13。
輸入S(S≤10)和若干郵票組合(郵票面值不超過100),選出最大連續郵資最大的一個 組合。如果有多個並列,郵票組合中郵票的張數應最多。如果還有並列,郵票從大到小排序 後字典序應最大。
分析:完全揹包,因爲組成最大的連續面值爲100*10=1000,所以可以用數組下標存儲。
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<sstream>
#include<cassert>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 1000+10;
int d[10+5][maxn];
int s;
int a[10 + 5][10 + 5];
int dp(int i1,int i2) {
int ok = 0;
d[i1][0] = 0;
for (int i = 1; i; i++) {
for (int j = 0; j < i2; j++) {
if (i - a[i1][j] >= 0) {
ok = 1;
if (d[i1][i - a[i1][j]] !=-1) {
d[i1][i] = min(d[i1][i],d[i1][i - a[i1][j]] + 1);
}
}
}
if (d[i1][i]>s)return i - 1;
}
}
int main() {
int n;
while (cin >> s && s) {
cin >> n;
int num[10+5];
memset(d, INF, sizeof(d));
for (int i = 0; i < n; i++) {
cin >> num[i];
for (int j = 0; j < num[i]; j++)
cin >> a[i][j];
}
int ans = 0;
int cnt = 0;
for (int i = 0; i < n; i++) {
int t = dp(i, num[i]);
if (t > ans) {
ans = t; cnt = i;
}
if (t == ans) {
int n1 = num[cnt], n2 =num[i];
if (n1 > n2) {
cnt = i;
}
else if (n1 == n2) {
while (n1-- > 0) {
if (a[cnt][n1] > a[i][n1]) {
cnt = i; break;
}
else if (a[cnt][n1] < a[i][n1])break;
}
}
}
}
printf("max coverage =%4d :", ans);
for (int i = 0; i < num[cnt]; i++) {
printf("%3d", a[cnt][i]);
}
cout << endl;
}
return 0;
}