HDU 5800 To My Girlfriend DP

Problem Description
Dear Guo

I never forget the moment I met with you.You carefully asked me: "I have a very difficult problem. Can you teach me?".I replied with a smile, "of course"."I have n items, their weight was a[i]",you said,"Let's define f(i,j,k,l,m) to be the number of the subset of the weight of n items was m in total and has No.i and No.j items without No.k and No.l items.""And then," I asked.You said:"I want to know

\[\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{k=1}^{n}\sum_{l=1}^{n}\sum_{m=1}^{s}f(i,j,k,l,m)\quad (i,j,k,l\quad are\quad different) \]

Sincerely yours,
Liao
Input
The first line of input contains an integer T(T≤15) indicating the number of test cases.
Each case contains 2 integers n, s (4≤n≤1000,1≤s≤1000). The next line contains n numbers: a1,a2,…,an (1≤ai≤1000).
Output
Each case print the only number — the number of her would modulo 109+7 (both Liao and Guo like the number).
Sample Input
2
4 4
1 2 3 4
4 4
1 2 3 4
Sample Output
8
8

**题意:**给出n个数,求权值和为m,没有下标i,j,有下标k,l的数集合个数 **思路:**主要是如何描述状态,权值大小,必不选取和必选取的状态的描述可以类似背包,dp[i][j][k][l] 代表选取到i个元素和为j,使用了k个必选名额,l个必不选名额 那么状态可以有四种转移方法 $$ \begin{equation}\label{Dirichlet}dp[i][j][k][l]+=\begin{cases} dp[i-1][j][k][l], & \text{ 不选当前的数,亦不作为必不选的数 }\\\ dp[i-1][j-a[i]][k][l], & \text{ 选当前的数,不作为必选的数 } \\\ dp[i-1][j-a[i]][k-1][l], & \text{ 选当前的数,作为必选的数 } \\\ dp[i-1][j][k][l-1], & \text{ 不选当前的数,但作为必}\color{#F00}{不}\text{选的数} \end{cases}\end{equation} $$
/** @Date    : 2016-11-09-17.37
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version :
*/
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <stack>
#include <queue>
#define LL long long
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+2000;
const int mod = 1e9 + 7;
int a[1010];
int dp[1010][1010][3][3];

LL solve(int &n, int &s)
{
MMF(dp);
dp[0][0][0][0] = 1;
//dp[1][0][0][0] = 1;
LL ans = 0;//返回值要用LL...
for(int i = 1; i <= n; i++)
{
for(int j = 0; j <= s; j++)
{
for(int k = 0; k <= 2; k++)
{
for(int l = 0; l <= 2; l++)
{
dp[i][j][k][l] += dp[i-1][j][k][l];
dp[i][j][k][l] %= mod;
if(j >= a[i])
{
dp[i][j][k][l] += dp[i-1][j-a[i]][k][l];
dp[i][j][k][l] %= mod;
}
if(k > 0)
{
if(j >= a[i])
dp[i][j][k][l] += dp[i-1][j - a[i]][k-1][l];
dp[i][j][k][l] %= mod;
}
if(l > 0)
{
dp[i][j][k][l] += dp[i-1][j][k][l-1];
dp[i][j][k][l] %= mod;
}
}
}
if(i == n)
{
ans += dp[i][j][2][2];
ans %= mod;
}
}
}
return (ans * 4 + mod) % mod;
}


int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, s;
scanf("%d%d", &n, &s);
for(int i = 1; i <= n; i++)
scanf("%d", a + i);
printf("%lld\n", solve(n, s));//输出LL型?
}
return 0;
}
posted @ 2016-11-09 17:52  Lweleth  阅读(136)  评论(0编辑  收藏  举报