Non-Interactive Guessing Number

题目

思路
1.猜数有两种极端:
1)最优策略:二分猜数,猜logn次
2)最差策略:猜两端未猜过的数(如 n=10 “>><<>” 那么我猜1,2,10,9,3),最多n次

2.若含有等于号,则我们要选择最优策略先猜,有以下两种情况
1)若在猜的中间(或者在最后一回合)我们就获胜了(l==r,即可输出“YES”),中间获胜的情况我们就可以在中间随便猜猜消耗一下次数,可以理解为最优和最差策略相结合
2)若在最后还是不能使得(l ==r),说明即使采取最优策略还是输,输出”NO“

3.不含等号:则随便猜猜即可,采取最差策略(只要a.size()<n)即可输出”YES“

注意
注意我代码中当区间长度为奇数且符号为‘<‘的左端点的赋值情况,因为题目说如果当Romanos猜的数为中间的数的时候,Theodora会说’<’

#include <iostream>
#include <string>
typedef long long ll;
using namespace std;
long long n;
int k;
string a;
bool slove()
{
    if(a.size()>n) return false;
    if(a[a.size()-1]=='=')
    {
        long long l=1,r=n;///记得开long long 
        for(int i=0; i<len-1; i++)
        {
            if(r<=l)  break;
            if((r-l+1)%2==0)///区间长度为偶数
            {
                if(str[i]=='<') r=(l+r)/2;///小于号取中间的数中间两个数中较小的那个
                if(str[i]=='>') l=(l+r)/2+1;///大于号取中间的数中间两个数中较大的那个
            }
            else///区间长度为奇数
            {
                ///因为题目说:当Romanos猜的数为中间的数的时候,Theodora会说'<'
                if(str[i]=='<') r=(l+r)/2-1;///所以小于号时Romanos猜的是中间的数,那么r变为中间的数-1:(l+r)/2-1
                if(str[i]=='>') l=(l+r)/2;///所以大于号时Romanos猜的是中间的数-1,那么L变为中间的数:(l+r)/2
            }
        }
        if(r!=l) return false;
    }
    if(a.size()==n) return false
    return true;
}
int main()
{
    cin>>n>>k;
    cin>>a;
    if(slove()) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

发布了95 篇原创文章 · 获赞 7 · 访问量 8457

猜你喜欢

转载自blog.csdn.net/Spidy_harker/article/details/100525752