很巧妙很经典的一道DP, 其中dp[n][x][y] 表示前n辆车装了x个装备1和y个装备2之后能装的最多的装备3的个数
,而把第n辆车上装的ix,iy装备去掉后就是前n-1辆车在拿了x - ix,y - iy个1,2装备后所能装的最大的装备3的个数
所以 dp[n][x][y] = max(dp[n - 1][x -ix x'][y - iy y'] + iz); 其中即x'=x - ix, y'=y - iy, 对ix和iy进行遍历即可得到
dp[n][x][y]; 而ix和iy的范围为第n辆车可以装的x和y的装备个数
由于空间限制,用滚动数组,(N-1维数组记录一个N维组合,然后对其DP求得最后一个数的方法就很棒)
#include <iostream> #include <cstring> #include <algorithm> #include <fstream> using namespace std; const int MAX_CAP = 501; const int MAX_CAR = 101; int dp[2][MAX_CAP][MAX_CAP]; //for dp the number of x,y,z int w[MAX_CAR]; //the weight that caravans can carry int s[MAX_CAR]; //the size that caravans can carry inline void getMax(int& a, int b) { if(a < b) a = b; } int main(int argc, char *argv[]) { // ifstream cin("input.txt"); int cas = 0; //for cout the cases //for cin the input int n; int w1, s1, d1; int w2, s2, d2; int w3, s3, d3; int c1, c2, c3, d4; while(cin>>n) { //the end of input if (n == 0) { return 0; } cin>>w1>>s1>>d1; cin>>w2>>s2>>d2; cin>>w3>>s3>>d3; cin>>c1>>c2>>c3>>d4; for (int i = 1; i <= n; ++i) { cin>>w[i]>>s[i]; } //init the dp array memset(dp[0], 0, sizeof(dp[0])); int max_x = 0, max_y = 0; //store the max number of x,y so far int prev = 0, now = 1; int tmp, nx, ny, nz; // record the max ny for (int i = 1; i <= n; ++i) { nx = min(w[i]/w1, s[i]/s1); //the number of x memset(dp[now], -1, sizeof(dp[now])); for (int j = 0; j <= nx; ++j) { ny = min((w[i]- j * w1)/w2, (s[i] - j * s1)/s2); if (j == 0) tmp = ny; for(int k = 0; k <= ny; ++k) { nz = min((w[i] - j * w1 - k * w2)/w3, (s[i] - j * s1 - k * s2)/s3); for (int a = 0; a <= max_x; ++a) { for (int b = 0; b <= max_y; ++b) { if (dp[prev][a][b] != -1) { getMax(dp[now][a + j][b + k], dp[prev][a][b] + nz); } } } } } max_x += nx; max_y += tmp; swap(now, prev); } //print the result if (cas ++) cout<<endl; int rst = 0; int def = max(0, d4 - c1 * d1 - c2 * d2 - c3 * d3); for (int i = 0; i <= max_x; ++i) { for (int j = 0; j <= max_y; ++j) { if (dp[prev][i][j] != -1) { int num = min(i/c1, j/c2); num = min(num, dp[prev][i][j]/c3); getMax(rst, i * d1 + j * d2 + d3 * dp[prev][i][j] + def * num); } } } cout<<"Case "<<cas<<": "<<rst<<endl; } return 0; }