97 分蒟蒻求助
  • 板块P1286 两数之和
  • 楼主dfs0ms
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/1/4 18:20
  • 上次更新2023/10/24 05:35:01
查看原帖
97 分蒟蒻求助
747401
dfs0ms楼主2023/1/4 18:20

代码里有注释 QAQQAQ

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 22;

int n, num, a[N * N];
int res[N];
bool vis[N][N]; /// vis[i][j] 表示 res[i] + res[j] 是否已经算过

bool check()
{
/// 考虑只有 4 个元素,当 j = 3,a[3] = a + d 或 b + c
/// 当 a[3] == b + c,令 a[3] 就等于 b + c
///		后三项一定为 d + (a / b / c),如果不相同,舍
/// 否则,令 a[3] = a + d,求出 d,继续计算
///		此时下一项一定为 b + c,如果 a[4] != b + c,舍
///		如果 a[4] == b + c,a[5] = b + d,a[6] = c + d
/// 不断看后一项,要么为之前求出的两个元素之和,要么新增一个元素,
///		当所有元素都已经求出,然而剩下的 a[] 中没有元素 = 已知两个元素的和,return false;
	int cnt = 2; /// 之前已经求出几个元素
	int pos = 1; /// 之前搞定了 a[1] - a[pos]
	while (pos < num)
	{
		bool flag = false; /// 能否由之前两个未使用的数相加得到
		pos++;
		for (int i = 1; i <= cnt; i++)
		{
			for (int j = i + 1; j <= cnt; j++)
				if ((!vis[i][j]) && res[i] + res[j] == a[pos]) {
					flag = true; vis[i][j] = true; break;
				}
			if (flag) break;
		}
	/// 从最小的数开始
		if (!flag) res[++cnt] = a[pos] - res[1];
	/// 无法再多制造一个元素 res[++cnt] = a[pos] - res[1]
		if (cnt == n + 1) return false;
	}
	return true;
}
int main()
{
	while (scanf("%d", &n) != EOF)
	{
		if (n == 2) { printf("Impossible\n"); continue; }
		num = n * (n - 1) / 2;
		for (int i = 1; i <= num; i++) scanf("%d", &a[i]);
		sort(a + 1, a + num + 1);

		bool key = false;
		for (int i = 0; i <= a[1] / 2; i++) /// 枚举 a,求出 b,res[3] 不确定
		{
			memset(vis, 0, sizeof(vis));
			res[1] = i; res[2] = a[1] - res[1]; vis[1][2] = true;
			if (check()) {
				for (int i = 1; i <= n; i++) printf("%d ", res[i]);
				printf("\n");
				key = true; break;
			}
		}
		if (!key) printf("Impossible\n");
	}
	return 0;
}
2023/1/4 18:20
加载中...