HDU 5800 To My Girlfriend 【DP】

来源:互联网 发布:网上公章制作软件 编辑:程序博客网 时间:2024/05/10 17:29

题意

有n个物品,每个物品的重量是ai,求以下式子:
ni=inj=1nk=1nl=1sm=1f(i,j,k,l,m)(ijkl)
其中f(i,jk,l,m)表示在所有物品中必选i和j,且必不选k和l,重量总和为m的选法总数。

分析

设状态dp[i][j][x][y]为选到第i个数时,总重量为j,必选了x个和必不选y个的选法总数。则在这个状态上我们可以再选一个,成为一个必选的或不是一个必选的;也可以不选,成为一个必不选的或是不是一个必不选的。也就是说可以转移给 dp[i+1][j+a[i]][x+1][y], dp[i+1][j+a[i]][x][y], dp[i+1][j][x][y+1] 和 dp[i+1][j][x][y]

AC代码

//HDU 5800 To My Girlfriend//AC 2017-1-19 09:55:33//DP#include <bits/stdc++.h>using namespace std;const int maxn=1e3+100;const int mod=1e9+7;int n,s;int a[maxn];int dp[maxn][maxn][3][3];int main(){    int T;scanf("%d",&T);    while(T--)    {        scanf("%d %d",&n,&s);        for(int i=0;i<n;++i)            scanf("%d",a+i);        memset(dp,0,sizeof dp);        dp[0][0][0][0]=1;        for(int i=0;i<n;++i)        {            for(int j=0;j<=s;++j)            {                for(int x=0;x<=2;++x)                {                    for(int y=0;y<=2;++y)                    {                        if(j+a[i]<=s)                        {                            if(x<2)                                dp[i+1][j+a[i]][x+1][y]=(dp[i+1][j+a[i]][x+1][y]+dp[i][j][x][y])%mod;                            dp[i+1][j+a[i]][x][y]=(dp[i+1][j+a[i]][x][y]+dp[i][j][x][y])%mod;                        }                        if(y<2)                            dp[i+1][j][x][y+1]=(dp[i+1][j][x][y+1]+dp[i][j][x][y])%mod;                        dp[i+1][j][x][y]=(dp[i+1][j][x][y]+dp[i][j][x][y])%mod;                    }                }            }        }        long long ans=0;        for(int i=0;i<=s;++i)            ans=(ans+dp[n][i][2][2])%mod;        cout<<(ans<<2)%mod<<endl;    }    return 0;}
0 0
原创粉丝点击