Codeforces Gym 100379L Game with a string 博弈+交互题

来源:互联网 发布:华为云服务器默认端口 编辑:程序博客网 时间:2024/06/05 15:35

题目大意:

有26堆石子,你可以选其中的若干堆取走每个选定堆中的一颗石子,没法取的人失败。你需要选择先手和后手,然后与程序交互,给出必胜的方案。

做法:

  • 我们先看只有一堆的情况,如果这一堆中的石子数为偶数,那么先手必败,反之如果是奇数,那么先手必胜;
  • 我们可以推广到26堆的情况,如果不存在奇数堆的石子那么先手必败,否则先手必胜。
  • 至此,我们得到了一个最优方案。如果不存在奇数堆的石子那么我们选则后手,否则选先手。
  • 每次将奇数堆的石子取走,使得对方面临必败状态即可。

代码:

#include <cstdio>#include <cstdlib>#include <cstring>#include <set>using namespace std;char str[1000];set<int>s[26];int hand=2,oper[1000],os,ct;bool get(){    int p;    scanf("%d",&os);    if(os==-1)return true;    while(os--)    {        scanf("%d",&p);        s[str[p-1]-'a'].erase(p);    }    return false;}int main(){    scanf("%s",str);    int len=strlen(str);    for(int i=0;i<len;i++)s[str[i]-'a'].insert(i+1);    for(int i=0;i<26;i++)        if(s[i].size()%2){hand=1;break;} //存在奇数堆选先手     printf("%d\n",hand);    fflush(stdout);    if(hand==2)get();    while(1){        int ct=0;        for(int i=0;i<26;i++)            if(s[i].size()%2)            {                oper[ct++]=*s[i].begin();                s[i].erase(s[i].begin());                //拿掉奇数堆             }        printf("%d",ct);        for(int i=0;i<ct;i++)printf(" %d",oper[i]);        printf("\n");        fflush(stdout);        if(get())break;    }    return 0;}
0 0
原创粉丝点击