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;
}