码迷,mamicode.com
首页 > 其他好文 > 详细

暑假集训 || 动态规划

时间:2018-08-28 23:54:14      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:贵的   集合   序列   fine   space   无法   很多   bsp   img   

·背包问题:

有很多的变式

HDU 2546
即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)
首先拿出5元买最贵的东西,那接下来就是背包容量m-5,物品数量 n-1 的01背包问题了
技术分享图片
if(m<5)    cout<<m<<endl;
else
{
    int f[1010];//f[j]表示买前i件物品,预算为j时的最大花销
    memset(f,0,sizeof(f));
    for(int i=1; i<=n-1; i++)
        for(int j=m-5; j>=price[i]; j--)
            if(f[j]<f[j-price[i]]+price[i])
                f[j]=f[j-price[i]]+price[i];
    cout<<m-max-f[m-5]<<endl;
}
View Code

 

CodeForces 544C
n个程序员要写m行程序,每个程序员在写一行程序时会产生ai个bug,写完m行共产生<=b个bug共有多少种方法
完全背包问题f[i][j][k]表示第i个程序员写了j行产生k个bug的方法时
f[i][j][k] = f[i-1][j][k] + f[i-1][j-1][k-a[i]] (考虑这个程序员这一行写或者不写)
技术分享图片
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int f[550][550], a[550];
int main()
{
    int n, m, b, mod;
    scanf("%d %d %d %d", &n, &m, &b, &mod);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    f[0][0] = 1;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            for(int k = a[i]; k <= b; k++)
                f[j][k] = (f[j][k] + f[j-1][k-a[i]]) % mod;
    int ans = 0;
    for(int i = 0; i <= b; i++) ans = (ans + f[m][i]) % mod;
    printf("%d\n", ans);
    return 0;
}
View Code

 

POJ 1837
一个臂长15的天平,在不同位置有钩子,钩子上可以挂砝码,给你G个砝码,要把所有砝码都挂在钩子上,一共有多少种挂法
f[i][j]表示挂了i个砝码,天平状态为j时的情况数,j=7500时表示平衡,j<7500向左倾斜,j>7500向右倾斜
技术分享图片
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
#define SZ 20100
int c[33], g[33];
int f[33][SZ];
int main()
{
    int C, G;
    scanf("%d %d", &C, &G);
    for(int i = 0; i < C; i++) scanf("%d", &c[i]);
    for(int i = 1; i <= G; i++) scanf("%d", &g[i]);
    memset(f, 0, sizeof(f));
    for(int i = 0; i < C; i++) f[1][7500 + g[1]*c[i]] = 1;
    int ans = 0;
    for(int i = 2; i <= G; i++)
        for(int j = 0; j < 15000; j++)
            for(int k = 0; k < C; k++)
                if(f[i-1][j] != 0)
                    f[i][j + g[i]*c[k]] += f[i-1][j];
    printf("%d\n", f[G][7500]);
    return 0;
}
View Code

 

HDU 4901
题意:一个序列,取两个集合A和B,使得A集合中所有元素在B集合的左边,并且A集合中所有元素的异或值等于B集合中所有元素的and值,求满足条件的集合数量
f[i][j]为前i个数异或值为j的方案数。g[i][j]为后i个数and值为j的方案数
考虑到在中间的分割点可能重复选择,dp[i][j]表示后i个数且第i个数一定被选择的方案数
然后乘法原理
技术分享图片
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
#define SZ 1010
const LL mod = 1e9+7;
LL f[SZ][1030], g[SZ][1030], dp[SZ][1030];
int a[SZ];
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= 1024; j++)
                f[i][j] = g[i][j] = dp[i][j] = 0;
        for(int i = 1; i < n; i++)
        {
            f[i][a[i]]++;
            for(int j = 0; j <= 1024; j++)
                if(f[i-1][j])
                {
                    f[i][j^a[i]] = (f[i][j^a[i]] + f[i-1][j]) % mod;
                    f[i][j] = (f[i][j] + f[i-1][j]) % mod;
                }
        }
        for(int i = n; i > 1; i--)
        {
            g[i][a[i]]++;
            dp[i][a[i]]++;
            for(int j = 0; j <= 1024; j++)
                if(g[i+1][j])//到i+1位时的方案数,i+1位可取可不取
                {
                    g[i][j] = (g[i][j] + g[i+1][j]) % mod;//到i位时的方案数,i位不取
                    g[i][j&a[i]] = (g[i][j&a[i]] + g[i+1][j]) % mod;//到i位时的方案数,i位取
                    dp[i][j&a[i]] = (dp[i][j&a[i]] + g[i+1][j]) % mod;//到i位时的方案数,i位必须取
                }
        }
        LL ans = 0;
        for(int i = 1; i < n; i++)
            for(int j = 0; j <= 1024; j++)
                ans = (ans + f[i][j] * dp[i+1][j]) % mod;
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

 

暑假集训 || 动态规划

标签:贵的   集合   序列   fine   space   无法   很多   bsp   img   

原文地址:https://www.cnblogs.com/pinkglightning/p/9551492.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!