whu1608 遍历子集dp

来源:互联网 发布:网页三剑客软件下载 编辑:程序博客网 时间:2024/05/02 01:06

题目大意:给你n个数和s,问最多将n分为多少组,使每组通过加减操作能得到s的组数最多,输出组数

#include <iostream>  #include <cstdio>  #include <cstring>  #include <algorithm>  using namespace std;  typedef long long lint;  int n, s, T, a[20];  int sum[1 << 20], f[1 << 20], g[1 << 20];  int main() {      //freopen( "A.in", "r", stdin );      scanf( "%d", &T );      while ( T -- ) {          scanf( "%d%d", &n, &s );          for ( int i = 0; i < n; i ++ ) {              scanf( "%d", &a[i] );          }          for ( int i = 0; i < (1 << n); i ++ ) {     //遍历所有子集              sum[i] = 0;              for ( int j = 0; j < n; j ++ ) if ( (i >> j) & 1 ) {                  sum[i] += a[j];              }          }          for ( int i = 0; i < (1 << n); i ++ ) {<span style="white-space:pre">        </span>//查看子集的子集是否有满足条件              f[i] = ( sum[i] == s );              for ( int j = (i - 1) & i; j; j = (j - 1) & i ) {                  f[i] |= ( sum[j] + s == sum[i - j] || sum[j] - s == sum[i - j] );              }          }          g[0] = 0;          int ans = 0;          for ( int mask = 0; mask < (1 << n); mask ++ ) {   //维护取最大值              g[mask] = f[mask];              for ( int sub = mask & (mask - 1); sub; sub = ( sub - 1 ) & mask ) {                  g[mask]    = max( g[mask], g[sub] + g[mask - sub] );              }              ans = max( ans, g[mask] );          }          cout <<ans<<endl;      }      return 0;  }  
0 0