排列算式(贪心策略)

链接:https://ac.nowcoder.com/acm/contest/10746/J
来源:牛客网

题目描述
给出n数字,对于这些数字是否存在一种计算顺序,使得计算过程中数字不会超过3也不会小于0?

输入描述
首行给出一个正整数 t , ( 1 ≤ t ≤ 1000 ) t,(1 \le t \le 1000) t,(1t1000)代表测试数据组数
每组测试数据第一行一个正整数 n , ( 1 ≤ n ≤ 500 ) n,(1 \le n \le 500) n,(1n500)
第二行包含 n n n个以空格分隔的数字
输入保证每一个数字都是 − 3 , − 2 , − 1 , + 0 , + 1 , + 2 , + 3 −3, −2, −1, +0, +1, +2, +3 3,2,1,+0,+1,+2,+3 的其中一个。

输出描述
每组测试数据输出一行,“Yes” or “No”

样例输入
2
4
+3 +2 -1 -2
5
+3 +2 +1 +0 +2

样例输出
Yes
No

解题思路
贪心,先考虑 − 3 -3 3,依次判断能否让 + 3 +3 +3 + 2 − 1 + 2 +2 -1 +2 +21+2 + 2 + 1 +2 +1 +2+1 + 1 + 1 + 1 +1 +1 +1 +1+1+1 把它中和掉,直到没有 − 3 -3 3 为止;若在中途没有东西能够中和 − 3 -3 3,则“NO”;
然后考虑 + 3 +3 +3,当 + 3 +3 +3 的个数大于1时,依次判断能否让 − 3 -3 3 − 2 + 1 − 2 -2 +1 -2 2+12 − 2 − 1 -2 -1 21 − 1 − 1 − 1 -1 -1 -1 111 把它中和,直到 + 3 +3 +3 个数小于等于1为止;若在中途没有东西能够中和 + 3 +3 +3,则“NO”;
若都没有“NO”,则“YES”。

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int T, n, a[7], *cnt;
bool check() {
	int t = 0;
	for (int i = -3; i <= 3; i++) {
		t += i * cnt[i];
	}
	if (t > 3 || t < 0) return false;

	//for -3, +3 || +2 +2 -1 || +2 +1 || +1 +1 +1
	t = min(cnt[-3], cnt[3]);
	cnt[-3] -= t;
	cnt[3] -= t;
	
	t = min(cnt[2], cnt[-1]);
	cnt[2] -= t;
	cnt[-1] -= t;
	cnt[1] += t;
	
	t = min(cnt[-3], cnt[1]);
	cnt[-3] -= t;
	cnt[1] -= t;
	cnt[-2] += t;
	
	if (cnt[-3] > 0) return false;
	
	// for 3, -3 || -2 -2 +1 || -2 -1 || -1 -1 -1
	t = min(cnt[-2], cnt[1]);
	cnt[-2] -= t;
	cnt[1] -= t;
	cnt[-1] += t;
	
	t = min(cnt[3], cnt[-1]);
	cnt[3] -= t;
	cnt[-1] -= t;
	cnt[2] += t;
	
	if (cnt[3] > 1) return false;
	return true;
}
int main() {
	//freopen("排列算式.in", "r", stdin);
	scanf("%d", &T);
	cnt = &a[3];
	while (T--) {
		memset(a, 0, sizeof(a));
		scanf("%d", &n);
		int t;
		for (int i = 1; i <= n; i++) {
			scanf("%d", &t);
			cnt[t]++;
		}
		if (check()) {
			printf("Yes\n");
		} else {
			printf("No\n");
		}
	}
	return 0;
} 
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值