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

    Problem 1608 - Calculation
     
    Description
    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 Sby + 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.
    Input
    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.
    Output
    For each test case, output one line with one integer without any space.
    Sample Input
    2
    5 5
    1 2 3 4 5
    5 5
    1 2 3 8 8
    Sample Output
    3
    2
     
    题意:
     
       给你n个数和S,
       让你把这N个数分成任意个集合块,集合块内可以通过任意加减 得到一个值,假如这个值等于S,则答案加一,问最大是多少
     
    题解:
        
       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[N],b[N ],c[N];
    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
    ",dp[(1<<n)-1]);
        }
        return 0;
    }
  • 相关阅读:
    PDA固定资产条码管理系统软件-解决固定资产实物清查的瓶颈问题,大大提高清查效率
    互联网+下PDA移动智能手持POS超市收银开单软件
    搭建免费代理池
    解析库beautifulsoup
    爬取汽车之家新闻
    请求库之requests库
    网络状态码301与302
    正向代理与反向代理
    垃圾回收机制详解
    HTTP协议详解
  • 原文地址:https://www.cnblogs.com/zxhl/p/5372337.html
Copyright © 2011-2022 走看看