POJ2184Cow Exhibition (01揹包變形)

思路一會兒就想到了,轉移方程卻沒想好,看到網上一個的思路相同的代碼,改的轉移方程。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;
}
相關文章
相關標籤/搜索