您的位置:首页 > 理论基础 > 计算机网络

第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 E Calculation 状态压缩DP枚举子集

2016-04-09 18:55 225 查看
[b]Problem 1608 - Calculation[/b]

[b]Description[/b]

Today, Alice got her math homework again!
She had n integers, and she needed to divide them into several piles or one pile. For each pile, if the teacher could get S, by + or – operator, then Alice got 1 small red flower. Alice wanted to get as many flowers as possible. Could you help her? Just tell her the maximum number of flowers she could get.

[b]Input[/b]
The input consists of several test cases.
The first line consists of one integer T (T <= 100), meaning the number of test cases.
The first line of each test cases consists of two integer n (n<=14), meaning the number of the integer, and S (0<= S<= 100000000), meaning the result which teacher wanted.
The next line consists of n integer a1, a2, …, an (0<= ai <= 10000000).
You should know a few cases that n is larger than 12.
[b]Output[/b]
For each test case, output one line with one integer without any space.
[b]Sample Input[/b]
2
5 5
1 2 3 4 5
5 5
1 2 3 8 8
[b]Sample Output[/b]
3
2

[b]题意:[/b]

   给你n个数和S,
   让你把这N个数分成任意个集合块,集合块内可以通过任意加减 得到一个值,假如这个值等于S,则答案加一,问最大是多少

[b]题解:[/b]

   N的范围是小于14
  容易想到状态压缩,
  我们就预处理出 每个子集 取的数的和 也就是全取正
  再通过不断取负号 为什么不用 不取的情况,因为子集会包含在内
  最后dp统计答案就好无聊

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int N = 1e5+10, M = 50, mod = 1e9+9, inf = 1e9+9;
typedef long long ll;

int dp[1<<15],n,m,a
,b[N ],c
;
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<(1<<n);i++) {
b[i] = 0;dp[i] = 0;c[i] = 0;
for(int j=0;j<n;j++) {
if(i&(1<<j)) b[i]+=a[j];
}
}
for(int i=0;i<(1<<n);i++) {
if(b[i]==m) c[i]=1;
for(int j=i;j;j = (j-1)&i) {
if(c[j]) {c[i] = 1;break;}
if(b[i]-b[j]-b[j]==m) {c[i] =1;break;}
}
}
for(int i=0;i<(1<<n);i++) {
dp[i] = 0;
for(int j=i;j;j = (j-1)&i) {
if(c[j]) dp[i] = max(dp[i], dp[i^j] + 1);
}
}
printf("%d\n",dp[(1<<n)-1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: