whu1608 遍历子集状压写法

本文介绍了一个使用C++实现的算法,该算法通过遍历所有可能的子集来解决一个特定的问题:即如何从一组整数中找出能通过加减运算得到目标值s的最多子集数量。代码详细展示了如何计算每个子集的总和,并判断这些子集是否满足题目要求。

题目大意:给你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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值