codeforces 1527B2 Palindrome Game (hard version) (博弈 / 贪心)

传送门
题解:通过 e a s y easy easy 版可以简单分析得到,如果一开始给的字符串是回文串,并且剩余 0 0 0 的个数为 1 1 1 的话,那么必然到了 A L I C E ALICE ALICE 得自己补上这个 0 0 0。如果剩余 0 0 0 的个数为偶数个的话,那么到了 A L I C E ALICE ALICE 也就是必须得先补上这个 0 0 0,之后 B O B BOB BOB 可以进行免费的 r e v e r s e reverse reverse 或者进行 A L I C E ALICE ALICE 补的那么 1 1 1 对应另一边也补为 1 1 1 B O B BOB BOB 依旧最后仍可进行免费的 r e v e r s e reverse reverse ,至少比 A L I C E ALICE ALICE 少花两块钱。但是如果刚开始剩余 0 0 0 的个数是奇数(是 1 1 1 上文已经分析)的话,那么 A L I C E ALICE ALICE 在第一次就把中间那个补上,也就回到了上文最近分析的那种情况,最后 A L I C E ALICE ALICE 也就至少比 B O B BOB BOB 少花一块钱。
到了 h a r d hard hard 版本,分析如果不是回文串,那么首先 A L I C E ALICE ALICE 必然可以先补 1 1 1 将其补为回文串来进行坑 B O B BOB BOB,或者就一直反转,让 B O B BOB BOB 不断来补,最后有个特例就是,如果串是奇数,并且中间为 0 0 0 ,并且一开始只有两个 0 0 0 ,那么就是平局,因为 A L I C E ALICE ALICE 一开始不补翻转的话,那么必然 B O B BOB BOB 把不是中间的那个 0 0 0 补为 1 1 1,也就是到了 A L I C E ALICE ALICE 必须自己补中间的这个 0 0 0,同理很好分析另外刚开始 A L I C E ALICE ALICE 一开始补,那么 B O B BOB BOB 也必须补。
核心思想:如果让对方补的更多,就是自己非得补也得尽量补出回文串。
代码:

#include<bits/stdc++.h>
#pragma GCC optimize(2)
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
#define pii pair<int,int>
#define pdd pair<double,double>
#define pll pair<long long,long long>
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define rush() int T;scanf("%d",&T);while(T--)
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%%d%%d",&a,&b)
#define sc3(a,b,c) scanf("%%d%%d%%d",&a,&b,&c)
#define pf(a) printf("%d\n",a)
#define pf2(a,b) printf("%d %d\n",a,b)
#define pf3(a,b,c) printf("%d %d %d\n",a,b,c)
#define debug(x) cout<<#x<<": "<<x<<endl
#define all(x) (x).begin(),(x).end()
#define PI acos(-1.0)
#define E exp(1.0)
#define ll long long
#define ld long double
#define ull unsigned long long
//#define io
using namespace std;
//#define gc getchar
char buf[1<<21],*p1=buf,*p2=buf;
inline int gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline int read(){
    int ret=0,f=0;char c=gc();
    while(!isdigit(c)){if(c=='-')f=1;c=gc();}
    while(isdigit(c)){ret=ret*10+c-48;c=gc();}
    if(f)return -ret;else return ret;
}
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

int main()
{
    rush() {
        int n;
        string s1, s2;
        cin >> n >> s1;
        s2 = s1;
        reverse(all(s1));
        int len = s1.size(), cnt = 0;
        rep(i, 0, len - 1) {
            if (s1[i] == '0') { 
                cnt++;
            }
        }
        if (cnt == 0) cout << "DRAW" << endl;
        else if (s1 == s2) cout << (cnt % 2 == 0 || cnt == 1 ? "BOB" : "ALICE") << endl;
        else {
            int mid = n / 2;
            if (n % 2 == 1 && cnt == 2 && s1[mid] == '0') cout << "DRAW" << endl;
            else cout << "ALICE" << endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值