2019-2020 ICPC Asia Taipei-Hsinchu Regional Contest I——The Spectrum dfs+剪枝

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
const int N = 2e3;
int n, arr[N + 5], cnt[N + 5], maxv;
vector<vector<int>> res;
vector<int> ans;
//现在多少数
//最大是多少
void solve(int u, int maxnow)
{
	if (u == n)
	{
		res.push_back(ans);
		sort(res.back().begin(), res.back().end());
		return;
	}
	//最大数 只能构建一次 如果是0了 那么就往前找最大的
	while (cnt[maxnow] == 0)
		--maxnow;
	//如果最大的次数 是 >2
	//那么这个方案就一定不合法
	if (cnt[maxnow] > 2)
		return;
	//如果为0 就说明是 maxnow -0
	//				   maxnow+k  -  (k+0)
	//同时加2 个
	if (cnt[maxnow] == 2)
	{
		bool ok = true;
		ans.push_back(maxnow);
		//构建k
		ans.push_back(maxv - maxnow);
		//当加入这两个数字之后
		//判断是否 是否还能构成原来的序列
		//也就是 check 有没有出现 没有出现过的差
		//同时也把能出现差的次数减去
		//那么最后构建的时候 最大的差就只是1 或者 2
		for(int i = 0; i < u; ++ i)
			if (-- cnt[abs(ans[i] - ans[u])] < 0)
				ok = false;
		for(int i = 0; i < u + 1; ++ i)
			if (-- cnt[abs(ans[i] - ans[u + 1])] < 0)
				ok = false;
		//如果没有出现过的话  那么就是可以继续往下找
		if(ok)
			solve(u + 2, maxnow);
		//不能 就 恢复现场
		for(int i = 0; i < u; ++ i)
			++ cnt[abs(ans[i] - ans[u])];
		for(int i = 0; i < u + 1; ++ i)
			++ cnt[abs(ans[i] - ans[u + 1])];
		ans.pop_back();
		ans.pop_back();
		return;
	}
	//只出现一次
	//就  只加入一个数字
	//分别check
	ans.push_back(maxnow);
	bool ok = true;
	for(int i = 0; i < u; ++ i)
		if (-- cnt[abs(ans[i] - ans[u])] < 0)
			ok = false;
	if(ok)
		solve(u + 1, maxnow);
	for(int i = 0; i < u; ++i)
		++ cnt[abs(ans[i] - ans[u])];
	ans.pop_back();

	ok = true;
	ans.push_back(maxv - maxnow);
	for(int i = 0; i < u; ++ i)
		if (-- cnt[abs(ans[i] - ans[u])] < 0)
			ok = false;
	if(ok)
		solve(u + 1, maxnow);
	for(int i = 0; i < u; ++i)
		++ cnt[abs(ans[i] - ans[u])];
	ans.pop_back();
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n * (n - 1) / 2; ++i)
	{
		cin >> arr[i];
		if (arr[i] >= 1000)
		{
			cout << 0 << endl;
			return 0;
		}
		cnt[arr[i]] += 1;
		//出现的最大数
		maxv = max(maxv, arr[i]);
	}
	//如果最大数出现了两次,那么就肯定有负数
	if (cnt[maxv] > 1)
	{
		cout << 0 << endl;
		return 0;
	}
	//x1 为0
	//那么最大就只能是maxv
	ans.push_back(0);
	ans.push_back(maxv);
	cnt[maxv] = 0;
	solve(2, maxv);
	sort(res.begin(), res.end());
	int sum = res.size();
	printf("%d\n", sum);
	for (int i = 0; i < sum; ++ i)
	{
		for (int j = 0; j < n; ++ j)
			cout<<res[i][j]<<" ";
		cout << endl;
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/QingyuYYYYY/p/12742452.html