二分法,互动(猜长方形,cf 713B)

来源:互联网 发布:算法导论第四章答案 编辑:程序博客网 时间:2024/06/04 19:25

第一次做互动的问题。就是你输出一次,它输入一次,它的输入是根据你的输出决定的。

给一个n*n的格子(2<=n<=2^16)。电脑事先想好2个不重叠的长方形,每个长方形都是由这些小格子为基本单位,然后告诉你n。你每次可以询问电脑任意一个矩形内有多少个长方形,电脑会告诉你有几个(0,1,2)。你必须在200次询问内猜出两个长方形的位置。


因为两个长方形不重叠,因此你总可以或横着切一刀,或竖着切一刀,把这个n*n的格子分成两部分,一部分有且只有一个长方形。

那就横着二分一下,找不到就竖着二分一下。然后问题就转换为两个相同的更简单的问题:在一个格子内确定一个长方形的位置。


分别二分上下左右边界,然后就找到了。


以下是  ! 2 2 2 2 3 4 4 4   的输入。


5
1
0
0
2
1
1
1
0
1
0
1
0
1
0
1
0
1
1
1
0
0
0
1
1
0



代码

#include<bits/stdc++.h>using namespace std;int n;struct rec{    int x1,y1,x2,y2;    rec(int a,int b,int c,int d):x1(a),y1(b),x2(c),y2(d){}};vector<rec>PRE;int Q(int x1,int y1,int x2,int y2){    if(x1>x2||y1>y2) return 0;    printf("? %d %d %d %d\n",x1,y1,x2,y2);    fflush(stdout);    int ans;    scanf("%d",&ans);    return ans;}void pre(){    int x=0,y=n+1,m;    while(x<y)    {        m=x+(y-x)/2;        int ans1=Q(1,1,m,n);        int ans2=Q(1+m,1,n,n);        if(ans1==1&&ans2==1)        {            PRE.push_back(rec(1,1,m,n));            PRE.push_back(rec(m+1,1,n,n));            return;        }        else if(ans1==0&&ans2==0) break;        else if(ans1) y=m;        else if(ans2) x=m+1;    }    x=0,y=n+1;    while(x<y)    {        m=x+(y-x)/2;        int ans1=Q(1,1,n,m);        int ans2=Q(1,1+m,n,n);        if(ans1==1&&ans2==1)        {            PRE.push_back(rec(1,1,n,m));            PRE.push_back(rec(1,1+m,n,n));            return;        }        else if(ans1==0&&ans2==0) break;        else if(ans1) y=m;        else if(ans2) x=m+1;    }}void solve(int x1,int y1,int x2,int y2){    int u,d,l,r;    int x,y,m;    x=0,y=y2-y1+2;    while(x<y)    {        m=x+(y-x)/2;        int ans=Q(x1,y1,x2,y1+m-1);        if(ans==1) y=m;        else x=m+1;    }    u=y1+x-1;    x=0,y=y2-y1+2;    while(x<y)    {        m=x+(y-x)/2;        int ans=Q(x1,y1+m,x2,y2);        if(ans==0) y=m;        else x=m+1;    }    d=y1+x-1;    x=0,y=x2-x1+2;    while(x<y)    {        m=x+(y-x)/2;        int ans=Q(x1+m,y1,x2,y2);        if(ans==0) y=m;        else x=m+1;    }    l=x1+x-1;    x=0,y=x2-x1+2;    while(x<y)    {        m=x+(y-x)/2;        int ans=Q(x1,y1,x1+m-1,y2);        if(ans==1) y=m;        else x=m+1;    }    r=x1+x-1;    PRE.push_back(rec(l,d,r,u));}int main(){    scanf("%d",&n);    pre();    solve(PRE[0].x1,PRE[0].y1,PRE[0].x2,PRE[0].y2);    solve(PRE[1].x1,PRE[1].y1,PRE[1].x2,PRE[1].y2);    printf("! %d %d %d %d %d %d %d %d\n",PRE[2].x1,PRE[2].y1,PRE[2].x2,PRE[2].y2,PRE[3].x1,PRE[3].y1,PRE[3].x2,PRE[3].y2);    fflush(stdout);    return 0;}


0 0
原创粉丝点击