[USACO21OPEN] Do You Know Your ABCs? S

题目描述

Farmer John 的奶牛正在 mooZ 视频会议平台上举行每日集会。她们发明了一个简单的数字游戏,为会议增添一些乐趣。

Elsie 有三个正整数 A、B 和 C,(1≤A≤B≤C)。这些数字是保密的,她不会直接透露给她的姐妹 Bessie。她告诉 Bessie N(4≤N≤7)个不同的整数 x1,x2...xn,并宣称每一个xi都是 A、B、C、A+B,B+C、C+A 或 A+B+C 之一。然而,Elsie 可能在撒谎;这些整数xi可能并没有对应任何一组合法的 (A,B,C)。Bessie 百思不得其解,所以需要靠你来求出与 Elsie 给出的数相符合的三元组 (A,B,C) 的数量。

每个输入包含 T(1≤T≤100)组需要独立求解的测试用例。

输入格式

输入的第一行包含 T。

每个测试用例的第一行包含 N,为 Elsie 给 Bessie 的整数的数量。

每个测试用例的第二行包含 N 个不同的整数 1,2,…,x1​,x2​,…,xN​。

输出格式

对于每个测试用例,输出与 Elsie 给出的数相符合的三元组 (A,B,C) 的数量。

输入输出样例

题目解析

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
//T:题目规定的总输入组数
//n:每组数的个数
//x[8]:用来表示给定数组,长度为4-7,多预留一位
//sum:当前有多少种组合
//a,b,c:表示A,B,C
//d[8]:根据大小关系表示给定数组的组合情况:A,B,C,A+B,A+C,B+C,A+B+C
int T, n, x[8], sum, a, b, c, d[8];
//用于检查是否有重复的三元组
int ax[1000005], bx[1000005], cx[1000005];
void dfs(int t) //t表示当前的位置,如果当前位置 t 超过数组 x 的长度,即已经考虑完所有的数字
{
	if (t > n)
	{
		//cout << "beging search" << endl;
		a = d[1], b = d[2], c = d[3];
		if (!d[4] && !d[5] && !d[6])
		{
			if (a + b + c == d[7] && a <= b && b <= c)sum++;
			return;
		}
		if (d[4])//已知A+B
		{
			if (a && !b && d[4] - a <= 0)return;
			else if (a && !b)b = d[4] - a; 
			if (!a && b && d[4] - b <= 0)return;
			else if (!a && b)a = d[4] - b; 
			if (a && b && a + b != d[4])return;
			if (d[7] && !c && d[7] - d[4] <= 0)return; 
			else if (d[7] && !c)c = d[7] - d[4]; 
			if (d[7] && c && d[7] - c != d[4])return;
		}
		if (d[5])
		{
			if (b && !c && d[5] - b <= 0)return;
			else if (b && !c)c = d[5] - b;
			if (!b && c && d[5] - c <= 0)return;
			else if (!b && c)b = d[5] - c;
			if (b && c && b + c != d[5])return;
			if (d[7] && !a && d[7] - d[5] <= 0)return;
			else if (d[7] && !a)a = d[7] - d[5];
			if (d[7] && a && d[7] - a != d[5])return;
		}
		if (d[6])
		{
			if (a && !c && d[6] - a <= 0)return;
			else if (a && !c)c = d[6] - a;
			if (!a && c && d[6] - c <= 0)return;
			else if (!a && c)a = d[6] - c;
			if (a && c && a + c != d[6])return;
			if (d[7] && !b && d[7] - d[6] <= 0)return;
			else if (d[7] && !b)b = d[7] - d[6];
			if (d[7] && b && d[7] - b != d[6])return;
		}
		if (a > b || b > c || a > c) return;
		if (a != d[1] && d[1])return;
		if (b != d[2] && d[2])return;
		if (c != d[3] && d[3])return;
		if (a + b != d[4] && d[4])return;
		if (b + c != d[5] && d[5])return;
		if (a + c != d[6] && d[6])return;
		if (a + b + c != d[7] && d[7])return;
		for (int i = 1; i <= sum; i++)
		{
			if (ax[i] == a && bx[i] == b && cx[i] == c)return; //检查是否有重复
		}
		sum++, ax[sum] = a, bx[sum] = b, cx[sum] = c;
		return;
	}
	for (int i = 1; i <= 7; i++)
	{
		if (d[i] == 0) {
			d[i] = x[t];
			if (d[1] <= d[2] || d[2] <= d[3]) {
				dfs(t + 1);
			}
			d[i] = 0;
		}
	}
}
int main()
{
	cin >> T;
	vector<int> ans;
	while (T--)
	{
		cin >> n;
		for (int i = 1; i <= n; i++) {
			cin >> x[i];
			d[i] = 0; // d[i]用来表示该位置的值是否已知,已知为该值,否则为0
		}
		sum = 0, dfs(1);
		ans.push_back(sum);
	}
	for (int j = 0; j < ans.size(); j++) {
		cout << ans[j] << endl;
	}
	return 0;
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值