poj 1882 Stamps 二维费用背包时间:2020-12-21 18:40:53//f[i][l][k]表示第i组数,话费l或l个以下的邮票可达到k价值//f[i][l][k] = f[i][l][k] | f[i][l - 1][k - a[i][j]] || f[i][l - 1][k];#include <iostream>#include <cmath>#include <cstring>#include <algorithm>using namespace std;bool f[10][11][1001];int n;int d[10];int a[10][10];int _max[10];int _maxIndex;int main() {//freopen("1.txt", "r", stdin);int s;while(cin >> s && s != 0) {cin >> n;for(int i = 0; i < n; i++) {cin >> d[i];for(int j = 0; j < d[i]; j++)cin >> a[i][j];}memset(f, false, sizeof(f));for(int i = 0; i < n; i++)for(int j = 0; j <= s; j++)f[i][j][0] = true;for(int i = 0; i < n; i++) {int maxV = a[i][d[i] - 1] * s;for(int j = 0; j < d[i]; j++) {for(int l = 1; l <= s; l++) {//万恶的循环,题目的5迷惑。。。for(int k = maxV; k >= a[i][j]; k--) {//f[i][l][k] = f[i][l][k] | f[i][l - 1][k - a[i][j]];f[i][l][k] = f[i][l][k] | f[i][l - 1][k - a[i][j]] || f[i][l - 1][k];}}}int j = 1;while(f[i][s][j]) j++;_max[i] = j - 1;if(i == 0) _maxIndex = 0;else if(_max[i] > _max[_maxIndex])_maxIndex = i;else if(_max[i] == _max[_maxIndex]) {if(d[i] < d[_maxIndex])_maxIndex = i;else if(d[i] == d[_maxIndex] && a[i][d[i] - 1] < a[_maxIndex][d[_maxIndex] - 1])_maxIndex = i;}}cout << "max coverage = " << _max[_maxIndex] << " :";for(int i = 0; i < d[_maxIndex]; i++)cout << " " << a[_maxIndex][i];cout << endl;} return 0;} 后来上网看到用完全背包的方法,自己尝试了一下,时间少了一半。。 //上网看的更优的算法:当作完全背包,最后看是否超过上限//f[j]表示构成价值j的邮票所需最小的邮票数#include <iostream>#include <cmath>#include <cstring>using namespace std;const int INF = 99999999;int f[1001];int n;int s;int d[10];int a[10][10];int _max;int index;int main() {//freopen("1.txt", "r", stdin);while(cin >> s && s != 0) {cin >> n;_max = 0;index = 0;for(int i = 0; i < n; i++) {cin >> d[i];for(int j = 0; j < d[i]; j++)cin >> a[i][j];int _maxV = a[i][d[i] - 1] * s;for(int j = 0; j <= _maxV; j++)f[j] = INF;f[0] = 0;for(int j = 0; j < d[i]; j++) {for(int k = a[i][j]; k <= _maxV; k++) {f[k] = min(f[k], f[k - a[i][j]] + 1);}}int tmp = 0;for(; tmp <= _maxV; tmp++)if(f[tmp] > s) break;tmp--;if(tmp > _max) {_max = tmp;index = i;}else if(tmp == _max) {if(d[i] < d[index]) {_max = tmp;index = i;}else if(d[i] == d[index] && a[i][d[i] - 1] < a[index][d[index] - 1]) {_max = tmp;index = i;}}}cout << "max coverage = " << _max << " :"; for(int i = 0; i < d[index]; i++) cout << " " << a[index][i]; cout << endl; } return 0;}