题解:P7345 【DSOI 2021】吟唱的金色花海

· · 题解

算法:二分和分治

注:代码和思路由 54zyd 和 willw 合作完成 (熬夜写了 5 个小时)。

大体思路

由题意得,(x_0,y_0) 与原始金色郁金香的曼哈顿距离刚好t。我们要做的就是通过询问来缩小原始金色郁金香可能出现的范围,直到剩下一个点。

特别警告:本题出入和询问输出的坐标都是编程中数组的坐标,而不是数学坐标。

算法实现

准备部分

二分部分

#include<bits/stdc++.h>
using namespace std;
int q,t,k,d;
int px,py;//预处理是加号还是减号 

bool ask(int x,int y){//询问点(x,y)在第t秒是不是金色郁金香 
    printf("0 %d %d\n",x,y);
    fflush(stdout);
    int f;
    scanf("%d",&f);
    return f==1;
}

void search(int x3,int y3){//二分部分 
    int l=0,r=t,mid;
    while(l<r){
        mid=ceil((l+r)/2.0);
        int x=x3+px*(mid+t/2),y=y3+py*(mid+t/2);
        if(ask(x,y)){
            l=mid;
        }
        else{
            r=mid-1;
        }
    }
    printf("1 %d %d\n",x3+px*l,y3+py*l);
    fflush(stdout);
}

int main(){
    scanf("%d",&q);
    int x0,y0;
    while(q--){//准备部分 
        scanf("%d%d%d%d",&t,&x0,&y0,&k);
        int f=ask(x0-1,y0),f1=ask(x0,y0+1);//将范围缩小到菱形的其中一条边上 
        int x3=x0,y3=y0;
        if(f){
            if(f1){
                x3-=t;
                px=1;
                py=1;
            }
            else{
                y3-=t;
                px=-1;
                py=1;
            }
        }
        else{
            if(f1){
                y3+=t;
                px=1;
                py=-1;
            }
            else{
                x3+=t;
                px=-1;
                py=-1;
            }
        }

        search(x3,y3);
    }
    return 0;
}

willw&54zyd:留下个赞再走吧 awa。