思路一會兒就想到了,轉移方程卻沒想好,看到網上一個的思路相同的代碼,改的轉移方程。ios
同時dp所有初始化爲負無窮,須要注意一下。spa
AC代碼以下:blog
/************************************************** Memory: 1884 KB Time: 250 MS Language: G++ Result: Accepted **************************************************/ #include <iostream> #include <cstdio> #include <cstring> using namespace std; /** 題目描述: n頭牛(1-n),每一個牛有兩個值Si和Fi,選其中任意頭,使s和f的和最大,其中s和f各自和都不能爲負數 */ int s[105], f[105]; int dp[200005]; int num[200005]; const int INF = 0x5f5f5f5f; int main() { int n; while (cin >> n) { int m = 0; for (int i = 0; i < n; ++i) { cin >> s[i] >> f[i]; s[i] += 1000; // 所有加上1000保證非負 m += s[i]; } for (int i = 0; i <= m; ++i) dp[i] = -INF; memset(num, 0, sizeof num); dp[0] = 0; // 保證全部dp的值都是正好裝滿。。 for (int i = 0; i < n; ++i) { for (int j = m; j >= s[i]; --j) { //if (dp[j] < dp[j - s[i]] + f[i]) if (dp[j] - num[j] * 1000 < dp[j - s[i]] + f[i] - (num[j - s[i]] + 1) * 1000) { // 這轉移方程我也是醉了。。保證的是s和爲j時s和f的和最大 dp[j] = dp[j - s[i]] + f[i]; num[j] = num[j - s[i]] + 1; // 記錄用了多少頭牛。。 } //printf("dp[%d]=%d, num[%d]=%d\n", j, dp[j],j, num[j]); } } int ans = 0; for (int j = 0; j <= m; ++j) { if (dp[j] >= 0 && j - num[j] * 1000 >= 0) ans = max(ans, dp[j] + j - num[j] * 1000); } cout << ans << endl; } return 0; }