NOJ-1085-花生米(四)

原博客:花生米(四)

花生米(四)

描述

五一长假第四天,Tom逛了N个bbs,做了N^2个脑筋急转弯题,终于发现了每次吃完花生米嘴里都是苦味的原因:自己总会吃到最后一粒花生米。
五一长假第五天,Tom和Jerry在仓库散步的时候发现了n堆花生米(这是什么仓库啊?!)。这次Tom制定分花生米规则如下:
1、首先选出最苦的一粒花生米,放到一个瓶子里;
2、Tom和Jerry轮流从任意一堆花生米中取出任意粒吃掉;
3、如果Tom吃到最后一粒花生米(瓶子里的花生米除外),Jerry必须吃掉瓶子里的花生米;如果Jerry吃到最后一粒花生米(瓶子里的花生米除外),Tom自愿吃掉瓶子里的花生米;
4、为显示规则的公平性,Jerry可以选择先取或者后取。
Jerry当然希望瓶子里的花生米被Tom吃掉。请计算,Jerry为了达到目的应该先取还是后取。

输入

本题有多个测例。
每个测例的输入第一行是一个整数n,n大于零小于等于10,代表花生米的堆数(取出最苦花生米后);接下来n行每行一个不超过100的正整数,分别代表一堆花生米的粒数(取出最苦花生米后)。
n等于0表示输入结束,不需要处理。

输出

每个测例在单独的一行内输出一个整数:Jerry先取输出1;Tom先取输出0。

输入样例

2
1
1
2
1
100
0

输出样例

0
1

思路

这个题对比与前两个花生米(二)花生米(三)

的区别在于前两个都是Jerry希望Tom拿到最后一颗花生米。现在这个题是Jerry希望自己拿到最后一颗花生米。并且 Tom和Jerry轮流从任意一堆花生米中取出任意粒吃掉。这个初看觉得比较复杂,所以我自己把情况分成了几种情况进行讨论:

1.只有1堆花生米,那Jerry必须先手,否则让Tom先手的话,Tom直接全部取走,先手必胜。所以Jerry要先取,答案输出1.(测试数据没有这个测试点)。

2.所有的花生堆都是1个为一堆,设有n堆,如果n是偶数,那么后手必胜,Jerry选择后手,答案输出0;如果n是奇数,那么先手必胜,Jerry选择先手,答案输出1。

3.如果存在花生数量>1的花生堆:

​ (1)如果总共就两堆花生:如果两堆数目一样,后手只要按照先手的取法跟着取就好了。后手必胜,输出0;否则先手必胜,输出1;

​ (2)如果花生堆数>2:这时候需要判断含1个花生米的堆数,和含>1个花生米的堆数。sign1=0表示只含一个花生米的堆数为偶数,sign2=0表示含>1个花生米的堆数为偶数。(这里偶数不含0,为0就表示不存在这种类型的花生堆,应该认为这时的sign=1)

​ 当sign1 == 1 &&sign2 == 1的时候: 全奇数堆先手必胜,所以Jerry必须先手:比如1 1 1 3 3 3–>1 3 3 3先手必胜 (后手无法赢)

​ 当存在偶数堆,则让对手取成全奇,在此之前,Jerry保持非全奇 :比如1 1 1 1 3 3 3 3 .如果先手选3,后手跟着选3,直到3用完,先手选择1,后手到达必胜态 。 如果 先手选3中的2,–>1 1 1 1 1 3 3 3 后手选 1–>1 1 1 1 3 3 3,直到3用完,先手选择1,后手到达必胜态。 同理1 1 1 3 3 3 3类型和1 1 1 1 3 3 3类型。

ps: 注意 7 3 3 3 3 3 3 3 这种类型即含1个花生米的堆数=0,这个时候sign1=1,sign2=1,就是指只存在奇数堆,先手必胜。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000+50;
int n,a[maxn];
int main(){
    while(1){
        cin>>n;
        if(n==0)break;
        int sum=0,cnt=0,tot=0; 
        for(int i=1;i<=n;i++){
            cin>>a[i],sum+=a[i];
            if(a[i]==1)cnt++;
        }
        if(n==1){
            cout<<1<<endl;
        }
        else if(cnt==n){
            if(n%2==0)cout<<0<<endl;
            else cout<<1<<endl;
        }
        else{
            if(n==2){
                if(a[1]==a[2])cout<<0<<endl;//对称取 
                else cout<<1<<endl;//Tom先手先让a[1]==a[2],Tom对称取,Jerry必败,所以Jerry必须先手 
            }
            else{
                int sign1=0,sign2=0;    
                if(cnt>0&&cnt%2==0)sign1=0;//只含1个花生米的堆数为偶数 
                else sign1=1;
                if((n-cnt)%2==0)sign2=0;//含>1个花生米的堆数为偶数 
                else sign2=1; 
                if(sign1&&sign2)cout<<1<<endl;//全奇数堆先手必胜,所以Jerry必须先手:比如1 1 1 3 3 3-->1 3 3 3先手必胜 (后手无法赢) 
                else cout<<0<<endl;//如果存在偶数堆,则让对手取成全奇,在此之前,Jerry保持非全奇 
                //如果1 1 1 1 3 3 3 3 .如果先手选3,后手跟着选3,直到3用完,先手选择1,后手到达必胜态
                //如果 先手选3中的2,-->1 1 1 1 1 3 3 3 后手选 1-->1 1 1 1 3 3 3,直到3用完,先手选择1,后手到达必胜态。
                //同理1 1 1 3 3 3 3类型和1 1 1 1 3 3 3类型。 
                //注意 7 3 3 3 3 3 3 3 这种类型即cnt==0,这个时候sign1=1,sign=1,就是指只存在奇数堆,先手必胜。 
            }
        }
    }
    return 0;
} 
/*7
3 3 3 3 3 3 3
*/
//Jerry 后手必胜的条件:后手且吃掉最后的花生米,则Jerry无法后手胜利。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Phoenix_ZengHao

创作不易,能否打赏一瓶饮料?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值