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

9 篇文章 0 订阅
9 篇文章 0 订阅

题目大意:

有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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值