codeforces 1010D 【二分+交互】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/88842442

题目链接:http://codeforces.com/problemset/problem/1011/D

题目让你在1到m之间猜一个数x,你每猜一个数,会得到三种回复,-1(x < y) ,0(x == y), 1 (x > y)。

而且每次回答都不一定是正确的回答,会根据一个序列 p,0为错误回答,1为正确回答,的规律回复你。

首先需要确定序列p,这里的方法是问 n次 数字1来得到回复,因为1已经是最小的数字,如果他回复是-1,可以充分说明当前的回答是错误的,以此得到序列p。

其次需要特别注意一句话:如果正确答案是t,只要回复的是t,那么这个答案就是正确的,如果回答是-t,那么这个答案就是错误的,这句话说明无论当前回答的是正确还是错误的答案,如果回复的是0,那么答案就是0。

在二分是的时候,不要因为因为当前答案是错误的就跳过不考虑,我们同样可以利用这个错误的答案。

如果当前回复的答案是错误的,为-1,那么可以说明 x >= y,其他情况也同理,但是这里可以直接写成 x > y,等于的情况可以去掉,因为上面提到如果相等的话,回答一定会是0而不是-1。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

const int Maxn = 1e5+10;
const int INF = 0x3f3f3f3f;

bool p[60];

int main(void)
{
    int n, m, ans;
    scanf("%d%d", &n, &m);
    memset(p, true, sizeof(p));
    for(int i = 0; i < m; ++i) {
        cout << 1 << endl;
        scanf("%d", &ans);
        if(ans == 0) return 0;
        if(ans == -1) p[i] = false;
    }
    int L = 1, R = n, mid, cur = 0;
    while(1) {
        mid = (ll)(L+R)/2;
        cout << mid << endl;
        scanf("%d", &ans);
        if(ans == 0) break;
        if(!p[cur]) {
            if(ans == -1) L = mid+1;
            else if(ans == 1) R = mid-1;
        } else {
            if(ans == -1) R = mid-1;
            else if(ans == 1) L = mid+1;
        }
        cur = (cur+1)%m;
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/88842442