完全背包

hdu 1248

水题额

int dp[N], v[] = {150, 200, 350};
void Init()
{
    for(int i = 1;i < N;++i)
        for(int j = 0;j < 3;++j)
        if(i >= v[j])
        dp[i] = max(dp[i], dp[i-v[j]]+v[j]);
}

int main()
{
    Init();
    int T;cin >> T;
    while(T--)
    {
        int n;cin >> n;
        cout << n - dp[n] << endl;
    }
    return 0;
}

hdu 1114

题意:T组样例,每组给重量空罐重量a,最后重量b,下面n组硬币规格,价值+重量,完全背包模板

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <stack>

using namespace std;

typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 100;
const int MOD = 1e9 + 9;

#define lson l, m, rt << 14
#define rson m + 1, r, rt << 1 | 1
#define F(i, l, r) for(int i = l;i <= (r);++i)
#define RF(i, l, r) for(int i = l;i >= (r);--i)

int dp[N], v[N], w[N];
int main()
{
    int T;cin >> T;
    while(T--)
    {
        memset(dp, 0x3f, sizeof(dp));
        int a, b;cin >> a >> b;b -= a;
        int n;cin >> n;
        F(i, 1, n) cin >> v[i] >> w[i];
        dp[0] = 0;//初始条件
        F(i, 1, n) F(j, w[i], b) if(dp[j - w[i]] != INF) dp[j] = min(dp[j], dp[j - w[i]] + v[i]);
        if(dp[b] == INF) puts("This is impossible.");
        else
            cout << "The minimum amount of money in the piggy-bank is " << dp[b] << "." << endl;
    }
    return 0;
}

hdu 2159

思路:dp[i][j]表杀i只怪,消耗j耐久值能获得的最大经验值

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <sstream>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iomanip>
#include <stack>

using namespace std;

typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 100;
const int MOD = 1e9 + 9;

#define lson l, m, rt << 14
#define rson m + 1, r, rt << 1 | 1
#define F(i, l, r) for(int i = l;i <= (r);++i)
#define RF(i, l, r) for(int i = l;i >= (r);--i)

int dp[N][N], v[N], w[N];
int main()
{
    int n, m, k ,s;
    while(cin >> n >> m >> k >> s)
    {
        F(i, 1, k) cin >> v[i] >> w[i];
        memset(dp, 0, sizeof(dp));
        F(i, 1, k) F(j, 1, s) F(z, w[i], m) dp[j][z] = max(dp[j][z], dp[j - 1][z - w[i]] + v[i]);
        bool flag = 1;
        for(int i = 1;i <= m && flag;++i)
            for(int j = 1;j <= s && flag;++j)
            if(dp[j][i] >= n) {flag = 0;cout << m - i << endl;}
        if(flag) puts("-1");
    }
    return 0;
}

POJ 3181

题意:问用1到k里面的数,组成n一共有多少种方案
思路:简单完全背包,但是输入n=1000,k=100时爆long long,根据计算n!大数思想,把一个大数拆成两部分即可

LL dp[N][5];
int main()
{
    LL n, k;
    LL p = 1e17;
    while(cin >> n >> k)
    {
        if(n == 0)
        {
            puts("0");
            continue;
        }
        dp[0][0] = 1;
        for(int i = 1;i <= k;++i)
            for(int j = i;j <= n;++j)
            {
                dp[j][1] = dp[j][1]+dp[j-i][1]+(dp[j][0]+dp[j-i][0])/p;
                dp[j][0] = (dp[j][0]+dp[j-i][0])%p;
            }
        if(dp[n][1]) cout << dp[n][1];
        cout << dp[n][0] << endl;
    }
    return 0;
}

以后再补题

posted @ 2019-05-25 21:49  谁知道你啊啊啊  阅读(262)  评论(0编辑  收藏  举报