• 洛谷 P3067 [USACO12OPEN]Balanced Cow Subsets G


    Description

    P3067 [USACO12OPEN]Balanced Cow Subsets G

    Solution

    又是一道折半搜索题。

    我们还是枚举一半的数,记录每一种情况的和。

    然后爆搜另一半,当和为 (S) 时,判断前一半是否可以凑出 (S),如果可以,打个标记即可。

    两次凑出 (S) 时,可能会有重复选用的数组,但其实不用管。

    考虑到重复的话,两边同时删去同一个数也相等,但可能选用相同的数会多次出现,所以要打个标记。

    (dfs) 过程中,状压记录一下当前选用了哪些数,加和减状压相同的状态也可以,前面证明过重复的数没有影响了。

    这道题由于还需要找到和为 (S) 的状态有哪些,可以用一个 (vector) 存一下,但是和太大了。

    所以还要用一个 (map) 离散化一下,不是真正的离散化,因为不需要排序,只需要标记一下即可。

    代码还是比较容易理解的。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <map>
    #include <vector>
    #define ri register int
    
    using namespace std;
    
    const int N = 30;
    const int S = (1 << 20) + 10;
    int n, mid, cnt;
    int a[N];
    map <int, int> mp;
    vector <int> g[S];
    bool vis[S];
    
    inline void dfs1(int x, int sum, int now){
    	// cout << "x  " << x << " " << now << endl;
    	if(x > mid){
    		if(!mp.count(sum)) mp[sum] = ++cnt;
    		g[mp[sum]].push_back(now);
    		return;
    	}
    	dfs1(x + 1, sum, now);
    	dfs1(x + 1, sum + a[x], now | (1 << (x - 1)));
    	dfs1(x + 1, sum - a[x], now | (1 << (x - 1)));
    }
    
    inline void dfs2(int x, int sum, int now){
    	if(x > n){
    		if(mp.count(sum)){
    			int t = mp[sum];
    			for(auto x : g[t])
    				vis[x | now] = 1;
    		}
    		return;
    	}
    	dfs2(x + 1, sum, now);
    	dfs2(x + 1, sum + a[x], now | (1 << (x - 1)));
    	dfs2(x + 1, sum - a[x], now | (1 << (x - 1)));
    }
    
    int main(){
    	scanf("%d", &n);
    	for(ri i = 1; i <= n; i++)
    		scanf("%d", &a[i]);
    	mid = n >> 1;
    	dfs1(1, 0, 0), dfs2(mid + 1, 0, 0);
    	ri ans = 0;
    	for(ri i = 1; i <= (1 << n); i++)
    		ans += vis[i];
    	printf("%d
    ", ans);
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15379931.html

  • 相关阅读:
    redis哨兵模式
    zookeeper 日志输出到指定文件夹
    Zookeeper运维问题集锦
    应用层、传输层、网络层常用协议
    链表排序
    集线器、交换机、路由器的区别
    C链表
    virtio/pass-through
    shell脚本实例
    KVM虚拟化相关-进阶
  • 原文地址:https://www.cnblogs.com/xixike/p/15379931.html
Copyright © 2020-2023  润新知