HDU 5800 To My Girlfriend(单调DP)

Posted forever97‘s blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5800 To My Girlfriend(单调DP)相关的知识,希望对你有一定的参考价值。

 

【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5800

 

【题目大意】

  给出一个容量上限s,f[i][j][k][l][m]表示k和l两个物品不能选,i和j两个物品必选,最终质量为m的方案数。求这些方案数的总和。

 

【题解】

  令dp[i][j][s1][s2]表示前i个物品填了j的体积,有s1个物品选为为必选,s2个物品选为必不选的方案数(0<=s1,s2<=2),则有转移方程dp[i][j][s1][s2]=dp[i-1][j][s1][s2]+dp[i-1][j-a[i]][s1-1][s2]+dp[i-1][j][s1][s2-1],边界条件为dp[0][0][0][0]=1,时间复杂度O(NS*3^2)。

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
typedef long long LL;
const int N=1005;
const LL mod=1e9+7;
int a[N],n,s,t,T;
LL dp[2][N][3][3],ans;
void add(LL &a,LL b){a=a+b;if(a>mod)a-=mod;}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&s);
        rep(i,n)scanf("%d",a+i);
        memset(dp,t=0,sizeof(dp));
        dp[0][0][0][0]=1;ans=0;
        rep(i,n){
            t^=1;
            for(int j=s;j>=0;j--){
                for(int u=0;u<3;u++)for(int v=0;v<3;v++){
                    dp[t][j][u][v]=dp[t^1][j][u][v];
                    if(j>=a[i])add(dp[t][j][u][v],dp[t^1][j-a[i]][u][v]);
                    if(u&&j>=a[i])add(dp[t][j][u][v],dp[t^1][j-a[i]][u-1][v]);
                    if(v)add(dp[t][j][u][v],dp[t^1][j][u][v-1]);
                } 
            }
        }rep(i,s)add(ans,dp[t][i][2][2]);
        ans=((ans*2)%mod)*2%mod;
        printf("%lld\n",ans);
    }return 0;
}

 

  

 

以上是关于HDU 5800 To My Girlfriend(单调DP)的主要内容,如果未能解决你的问题,请参考以下文章

To my future girlfriend

Me-and-My-girlfriend-1靶机实战-vuluhub系列(完结)

美语初级 L051:My Girlfriend 解析

vulnhub靶机之Me and My Girlfriend: 1

CISP-PTE靶机练习(me-and-my-girlfriend)

CISP-PTE靶机练习(me-and-my-girlfriend)