DP 做題記錄
阿新 • • 發佈:2021-07-17
#include <stdio.h> #include <string.h> #include <iostream> #define cin std::cin #define cout std::cout #define endl std::endl const int N = 210; const int M = 21; int T, n, m, dp[M][M*M*2]; int from[N][M][M*M*2]; int a[N], b[N], choose[M]; int anscnt, D, P; bool check(int x) { return x<0 || x>800; } int f(int x, int tag) { return tag * x + 400; } void getans(int I, int J, int K) { if (!J) return ; // which didn't choose anyone int From = from[I][J][K]; // next I is the From getans(From-1, J-1, K-a[From]+b[From]); choose[++anscnt] = From; D += a[From], P += b[From]; return ; } int main() { while (cin >> n >> m) { ++T, anscnt = 0, D = P = 0; // testcase if (!n && !m) return 0; for (int i=1; i<=n; ++i) cin >> a[i] >> b[i]; memset(dp, 0xcf, sizeof dp); // get the maximum, so set the minimum dp[0][400] = 0; // set 0 -> 400, as the first-val memset(from, 0, sizeof from); for (int i=1; i<=n; ++i) { for (int j=0; j<=m; ++j) for (int k=0; k<=800; ++k) from[i][j][k] = from[i-1][j][k]; for (int j=m; j >= 1; --j) for (int k=0; k<=800; ++k) { int cur = k - a[i] + b[i]; // which position the value comes from if (check(cur)) continue; // just choose this position if (dp[j][k] < dp[j-1][cur] + a[i] + b[i]) { dp[j][k] = dp[j-1][cur] + a[i] + b[i]; from[i][j][k] = i; } } } int pos = 0; for (int i=0; i<=400; ++i) { if (dp[m][f(i,1)] >= 0 && dp[m][f(i,1)] >= dp[m][f(i,-1)]) { pos = f(i,1); break; } else if (dp[m][f(i,-1)] >= 0) { pos = f(i,-1); break; } } getans(n, m, pos); // through the paths, to get the answers cout << "Jury #" << T << endl; cout << "Best jury has value " << D; cout << " for prosecution and value " << P; cout << " for defence:" << endl; for (int i=1; i<=anscnt; ++i) cout << ' ' << choose[i]; puts(""), puts(""); } }