uva242
題目描述:假定一張信封最多貼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; }?
總結