AtCoder Regular Contest 070 F - HonestOrUnkind 交互题

题意

这是一道交互题。
有n个人,其中a个是诚实的,另外b=n-a个是不诚实的。每次你可以对x询问y是否诚实,若x是诚实的则会如实回答,否则的话就会按照某种策略随意回答。
问能否通过不超过2n次询问确定每个人是否诚实
a , b 2000

分析

首先若 a b 则无解,因为我们可以选出 a 个不诚实的人去假扮诚实的人。
很显然的思路就是要去找到一个诚实的人,然后扫一遍就可以得到答案了。
那么我们可以考虑构造一条链 x 1 , x 2 , . . . , x k ,其中第 x i 个人说第 x i + 1 个人是诚实的。
若其中存在某个人是诚实的,那么链最末端那个人就一定是诚实的。
考虑维护一个栈,当栈顶元素说另外一个人是不诚实时,这两个人一定至少有一人是不诚实的,那么就把它们抵消掉。
因为 a > b ,所以到后面一定可以得到一个诚实的人,然后就做完了。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

const int N=10005;

int a,b,n,stack[N],ans[N];

int main()
{
    scanf("%d%d",&a,&b);
    if (a<=b) {printf("Impossible");return 0;}
    n=a+b;
    int top=0,re;
    for (int i=1;i<n;i++)
    {
        if (!top) {stack[++top]=i;continue;}
        printf("? %d %d\n",stack[top],i);
        fflush(stdout);
        char op[2];scanf("%s",op);
        if (op[0]=='N') top--;
        else stack[++top]=i;
    }
    re=stack[top];
    for (int i=0;i<n;i++)
    {
        printf("? %d %d\n",re,i);
        fflush(stdout);
        char op[2];scanf("%s",op);
        if (op[0]=='N') ans[i]=0;
        else ans[i]=1;
    }
    printf("! ");
    for (int i=0;i<n;i++) putchar(ans[i]+'0');
    puts("");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_33229466/article/details/80483613