(2022牛客多校五)C-Bit Transmission(思维)

该博客讨论了一道编程竞赛题目,涉及对01字符串的询问和错误处理。题目要求通过最多一次错误的询问结果来唯一确定字符串,博客作者分析了各种可能情况并提供了代码实现,但指出由于数据问题导致部分测试用例未能正确处理。文章重点在于错误检查和字符串确定条件的判断逻辑。
摘要由CSDN通过智能技术生成

题目:

样例输入: 

3
0 NO
1 YES
2 YES
0 YES
1 YES
2 YES
0 YES
1 YES
2 YES

样例输出:

111

题意:有个01组成的字符串,对某些位置询问是否是1 询问3*n次

有至多一次询问 返回的答案是错误的,也可以是所有的询问都是正确的

问这些询问结果能否唯一确定字符串。

这道题目比赛的时候因为数据问题疯狂wa,即使到最后改完数据还是有一些错误,一会我会说出数据错误的地方。

先来分析一下这道题,首先我们需要记录一下每一位上被询问得到是1/0的次数,记作cnt[i][1/0]

如果某一位一直没被询问,也就是说cnt[i][1]=cnt[i][0]=0,那么这肯定是无法唯一确定的 

当cnt[i][0]>1,cnt[i][1]>1时也是错误的,因为题意种说明了能够允许的错误次数不超过1次

如果存在cnt[i][1]=cnt[i][0]=1那么也是不能唯一确定的,因为我们无法确定他是哪一次说的慌

我们还需要一个id来记录说谎的位置,比如某一个i是cnt[i][1]>1,cnt[i][0]=1,那么显然就是说第i位为0的那次说了慌,这样的说谎位置最多只能有一个,否则也是不符合题意的

除了上面的这一些情况,还有一种不行的情况,也是数据出bug的地方,就是说如果某个位置只被询问了一次,而此时没有一个位置是我们能够确定他一定说谎的,那么这种情况下无论他说不说谎都是说谎次数小于等于1的,所以这种情况也是没办法得到唯一解的,但是数据中有符合这种情况的,但是答案却给错了,赛后我测试了一下,加上这种情况能过96%,但是不考虑这种情况就能通过全部数据,我觉得还是严谨点比较好,所以下面给出的代码是考虑了这种情况的代码:

此代码不能通过赛题,如若想通过赛题,请注释我代码种注明的那条语句

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e5+10;
int cnt[N][2];
char s[10];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=1;i<=n;i++) cnt[i][0]=cnt[i][1]=0;
		int t;
		for(int i=1;i<=3*n;i++)
		{
			scanf("%d%s",&t,s);
			if(s[0]=='Y') cnt[t+1][1]++;
			else cnt[t+1][0]++;
		}
		int id=0;
		int cntt=0;//cntt记录第i个位置只有一个询问的位置个数 
		bool flag=true;
		for(int i=1;i<=n;i++)
		{
			if(cnt[i][0]>=2&&cnt[i][1]>=2)
			{
				flag=false;
				break;
			}
			if(cnt[i][0]==cnt[i][1])//要么都没有被问过,要么都被问过一次 
			{
				flag=false;
				break;
			}
			if((cnt[i][0]>0&&cnt[i][1]==0)||(cnt[i][0]==0&&cnt[i][1]>0))
			{
				if(cnt[i][0]==1||cnt[i][1]==1) cntt++;
				continue;
			}
			if(cnt[i][0]==1&&cnt[i][1]>1)
			{
				if(id)
				{
					flag=false;
					break;
				}
				else id=i;
			}
			else if(cnt[i][0]>1&&cnt[i][1]==1)
			{
				if(id)
				{
					flag=false;
					break;
				}
				else id=i;
			}
		}
		if(!id&&cnt) flag=false;//题目数据有问题,注释此语句即可AC 
		if(flag)
		{
			for(int i=1;i<=n;i++)
				if(i==id)
				{
					if(cnt[i][0]>1) printf("0");
					else printf("1");
				}
				else
				{
					if(cnt[i][0]>0) printf("0");
					else printf("1");
				}
			puts("");
		}
		else
			puts("-1");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值