http://acm.hdu.edu.cn/showproblem.php?pid=5800
题意:
给定一个由n个元素组成的序列,和s (n<=1000,s<=1000)
求 :
题解的做法是f[i][j][s1][s2]表示前i个数总和为j必选s1个必不选s2个的方案数,这样是O(n*s*4)的。
对于每一个数,有4种选法:选,不选,必选,必不选,然后转移就好了。
答案就是sigma(f[n][i][2][2]) ,i∈[0,s]。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <ctime> 8 #include <queue> 9 #include <list> 10 #include <set> 11 #include <map> 12 using namespace std; 13 #define mod 1000000007 14 typedef long long LL; 15 16 int dp[1010][1010][4][4]; 17 int a[1010]; 18 void Add(int &x, int y) 19 { 20 x = (x + y) % mod; 21 } 22 int main() 23 { 24 int n, s, t; 25 scanf("%d", &t); 26 while(t--) 27 { 28 scanf("%d %d", &n, &s); 29 for(int i = 1; i <= n; i++) 30 scanf("%d", a + i); 31 memset(dp, 0, sizeof(dp)); 32 dp[0][0][0][0] = 1; 33 for(int i = 1; i <= n; i++) 34 { 35 for(int j = 0; j <= s; j++) 36 { 37 for(int k = 0; k <= 2; k++) 38 { 39 for(int l = 0; l <= 2; l++) 40 { 41 Add(dp[i][j][k][l], dp[i - 1][j][k][l]); 42 if(j >= a[i]) 43 Add(dp[i][j][k][l], dp[i - 1][j - a[i]][k][l]); 44 if(k > 0 && j >= a[i]) 45 Add(dp[i][j][k][l], dp[i - 1][j - a[i]][k - 1][l]); 46 if(l > 0) 47 Add(dp[i][j][k][l], dp[i - 1][j][k][l - 1]); 48 } 49 } 50 } 51 } 52 LL res = 0; 53 for(int i = 0; i <= s; i++) 54 res += dp[n][i][2][2]; 55 printf("%lld ", res * 4 % mod); 56 } 57 return 0; 58 }