hdu5800 To My Girlfriend(dp)

来源:互联网 发布:prezi软件破解版 编辑:程序博客网 时间:2024/06/05 11:07

hdu5800

题目

给定n个数,其中选定若干数,这若干数的权值和为m,且这些数中没有下标为i,j的数,有下标为k,l的数的集合个数。

思路

dp[i][j][s1][s2],代表的是前i个物品,总权值为j,已有s1个必选,s2必不选的方案数。有四种转移方式,记得最后*4。

代码

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>using namespace std;typedef long long ll;const int mod=1e9+7;int dp[1005][1005][3][3];int a[1005];int n,s;int main(){    int T;    scanf("%d",&T);    while(T--)    {        memset(dp,0,sizeof(dp));        scanf("%d %d",&n,&s);        for(int i=1; i<=n; i++) scanf("%d",&a[i]);        dp[0][0][0][0]=1;        for(int i=1; i<=n; i++)        {            for(int j=0; j<=s; j++)                for(int k=2; k>=0; k--)                    for(int h=2; h>=0; h--)                    {                        dp[i][j][k][h]+=dp[i-1][j][k][h];                        dp[i][j][k][h]%=mod;                        if(j-a[i]>=0)                        {                            dp[i][j][k][h]+=dp[i-1][j-a[i]][k][h];                            dp[i][j][k][h]%=mod;                            if(k)                            {                                dp[i][j][k][h]+=dp[i-1][j-a[i]][k-1][h];                                dp[i][j][k][h]%=mod;                            }                        }                        if(h)                        {                            dp[i][j][k][h]+=dp[i-1][j][k][h-1];                            dp[i][j][k][h]%=mod;                        }                    }        }        ll sum=0;        for(int i=1; i<=s; i++)        {            sum+=dp[n][i][2][2];            sum%=mod;        }        printf("%I64d\n",sum*4%mod);    }    return 0;}
0 0
原创粉丝点击