0 vs 1 2023“钉耙编程”中国大学生算法设计超级联赛(8)hdu7365

Problem - 7365

题目大意:有一个长度为n的01字符串,A先手,只能拿位于两端的0,B后手,只能拿位于两端的1,谁不能拿了就输,但都拿完是平局,问最终结果

1<=n<=1e5

思路:我们考察字符串的两端分别有哪几种情况,首先如果两端的数字不一样,一个是0一个是1,那么当前行动的人没有选择,只能拿自己能拿的那一个,如果两端都是0,且当前轮到1行动,那么B就输了,同理如果两端都是1且当前轮到0行动,A输了

当两端都是0且轮到0行动时,如果有某一端有两个连续的0,那么它只要拿掉那端的一个0就赢了,剩下的情况就是每个0后面都至少有一个1,如果某一端是010这种情况,那A把这端的0拿掉,1只能拿这后面的1,就又回到了两端都是0的状态,所以遇到010的我们直接跳过到后面的0,如果当前剩余的数只有4个也就是0110这种情况,那么就都会被拿完,平局,否则如果两端出现011...110或01...1110的情况,A都会输,也就是两端的0后面3个位置的1数量加起来大于等于4A就会输,那么当前所有可能情况就都讨论完毕了,剩下当前1行动且两端都是1的情况与刚才的讨论类似

#include
//#include<__msvc_all_public_headers.hpp>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int n;
void solve()
{
    cin >> n;
    string s;
    cin >> s;
    int l = 0;
    int flag = 0;//当前谁行动
    int r = n - 1;//用双指针维护当前剩余的字符串
    while (l <= r)
    {
        if (l == r)
        {//只剩一个要么有人赢要么平局
            if (s[l] == '0')
            {
                cout << (flag ? 0 : -1) << endl;
            }
            else
            {
                cout << (flag ? -1 : 1) << endl;
            }
            return;
        }
        if (!flag && s[l] != s[r])
        {//两端不一样那么当前的行动是唯一的
            if (s[r] == '0')
            {
                r--;
            }
            else
            {
                l++;
            }
            flag ^= 1;
        }
        else if (flag && s[l] != s[r])
        {
            if (s[r] == '1')
            {
                r--;
            }
            else
            {
                l++;
            }
            flag ^= 1;
        }
        else if (!flag && s[l] == s[r] && s[r] == '1')
        {//两端都为1,当前A操作,A输
            cout << 1 << endl;
            return;
        }
        else if (flag && s[l] == s[r] && s[r] == '1')
        {//两端都为1,1操作
            if (s[l] == s[l + 1] || s[r] == s[r - 1])
            {//有一端有连续的两个相同数
                cout << 1 << endl;
                return;
            }
            while (l + 2 <= r && s[l + 1] == '0' && s[l + 2] == '1')
            {//遇到101可以直接跳到后面的1
                l += 2;
            }
            while (r - 2 >= l && s[r - 1] == '0' && s[r - 2] == '1')
            {
                r -= 2;
            }
            if ((l + 2 <= r && s[l + 1] == '0') && (r - 2 >= l && s[r - 1] == '0'))
            {//1后面都是0
                if (r - l == 3)
                {//长度为4平局
                    cout << -1 << endl;
                    return;
                }
                int cnt = 0;
                for (int i = l + 1; i <= l + 3; i++)
                {//统计每个1后三个位置0的数量
                    cnt += s[i] - '0'+1;
                }
                for (int i = r - 1; i >= r - 3; i--)
                {
                    cnt += s[i] - '0'+1;
                }
                if (cnt >= 4)
                {有4个0就输了
                    cout << 0 << endl;
                    return;
                }
            }

        }
        else if (!flag && s[l] == '0' && s[r] == '0')
        {
            if (s[l] == s[l + 1] || s[r] == s[r - 1])
            {
                cout << 0 << endl;
                return;
            }
            while (l + 2 <= r && s[l + 1] == '1' && s[l + 2] == '0')
            {
                l += 2;
            }
            while (r - 2 >= l && s[r - 1] == '1' && s[r - 2] == '0')
            {
                r -= 2;
            }
            if ((l + 2 <= r && s[l + 1] == '1') && (r - 2 >= l && s[r - 1] == '1'))
            {
                if (r - l == 3)
                {
                    cout << -1 << endl;
                    return;
                }
                int cnt = 0;
                for (int i = l + 1; i <= l + 3; i++)
                {
                    cnt += s[i] - '0';
                }
                for (int i = r - 1; i >= r - 3; i--)
                {
                    cnt += s[i] - '0';
                }
                if (cnt >= 4)
                {
                    cout << 1 << endl;
                    return;
                }
            }

        }
        else if (flag && s[l] == '0' && s[r] == '0')
        {
            cout << 0 << endl;
            return;
        }
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

你可能感兴趣的:(贪心,算法,c++,数据结构)