选数 中途相遇搜索

题目

题目在这里

思路

就是个搜索啊

代码

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <set>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 25;

int a[N];

int n;

struct Data
{	int val, status;
	bool operator < (const Data & rhs) const { return val < rhs.val; }
} num[1000010];
int tot;

void dfs_1(int x, int sum, int S)
{	if(x == n/2+1)
		num[++tot] = (Data){sum, S};
	else
	{	dfs_1(x+1, sum, S);
		dfs_1(x+1, sum-a[x], S|(1<<x));
		dfs_1(x+1, sum+a[x], S|(1<<x));
	}
}

bool vis[2097153];

void dfs_2(int x, int sum, int S)
{	if(x == n+1)
	{	int l = lower_bound(num+1, num+1+tot, (Data){-sum, 0}) - num;
		int r = upper_bound(num+1, num+1+tot, (Data){-sum, 0}) - num;
		for(int i=l; i<r; i++)
			vis[S|num[i].status] = 1; //大神犇tzw说这样可能会T
	}
	else
	{	dfs_2(x+1, sum, S);
		dfs_2(x+1, sum-a[x], S|(1<<x));
		dfs_2(x+1, sum+a[x], S|(1<<x));
	}
}

int main()
{	scanf("%d", &n);
	for(int i=1; i<=n; i++)
		scanf("%d", &a[i]);
	dfs_1(1, 0, 0);
	sort(num+1, num+1+tot);
	dfs_2(n/2+1, 0, 0);
	int ans = 0;
	for(int i=0; i<=2097152; i++) if(vis[i]) ans++; //千万不要用set去重, 特别慢
	printf("%d\n", ans-1);
	return 0;
}

配注

其实这是我第一次写中途相遇搜索

写了一坨bug

posted @ 2018-04-04 17:20  EZ_WYC  阅读(121)  评论(0编辑  收藏  举报