【题解】CF1503B 3-Coloring

题面传送门

解决思路

讲一下 \(\text{VP}\) 时的思路。

首先想到,只要能将棋盘中红色或蓝色部分全部填成同一个数,那么剩下的就不会受限了(可行有两个,限制只有一个):

但考虑到交互库可能有点坑,比如第一个给了 \(1\),你钦定了红色块全填 \(2\),但后面他可能一直给 \(2\) 。这样的话,你只能再钦定蓝色块全填 \(1\) 。所以需要 “双线并行” ,直到填满其中一种为止。

可以证明,是一定存在这样的一组可行解的。

注意:随意填时填的数不能和给出的数相同。为了找出这个错误笔者甚至写了一个简陋的交互库。。。

具体解释可以看代码。

AC Code

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
#define TIE cin.tie(0),cout.tie(0)
using namespace std;
int n,ans[105][105],t1,t2,op,cnt1,cnt2;
int tot1,tot2;
struct node{
	int x,y;
}a1[10005],a2[10005];
bool fl;
int main(){	
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if((i+j)%2==0) a1[++tot1].x=i,a1[tot1].y=j;
			else a2[++tot2].x=i,a2[tot2].y=j;
		}
	}    
	//预处理红色块、蓝色块的位置
    
	cin>>op;  
	if(op==1) cout<<2<<' ',t1=2;
	if(op==2) cout<<3<<' ',t1=3;
	if(op==3) cout<<1<<' ',t1=1;
	cnt1++;
	cout<<a1[cnt1].x<<' '<<a1[cnt1].y<<endl;
	//钦定红色块全填什么
        
	for(int i=1;i<=n*n-1;i++){
		cin>>op;
		if(op==t1&&!fl){
			if(op==1) cout<<2<<' ',t2=2;
			if(op==2) cout<<3<<' ',t2=3;
			if(op==3) cout<<1<<' ',t2=1;
			cnt2++;
			cout<<a2[cnt2].x<<' '<<a2[cnt2].y<<endl;
			fl=1;
		}
        //钦定蓝色块全填什么
        
		else if(op==t1&&cnt2<tot2){
			cout<<t2<<' ';
			cnt2++;
			cout<<a2[cnt2].x<<' '<<a2[cnt2].y<<endl;
		}
        //往蓝色块填数
        
		else if(op==t1){
			for(int z=1;z<=3;z++){
				if(z!=t1&&z!=t2){
					cout<<z<<' ';
					break;
				}
			}
			cnt1++;
			cout<<a1[cnt1].x<<' '<<a1[cnt1].y<<endl;
		}
        //蓝色块填满了就往红色块填可行数
        
		else if(cnt1<tot1){
			cout<<t1<<' ';
			cnt1++;
			cout<<a1[cnt1].x<<' '<<a1[cnt1].y<<endl;
		}
        //往红色块填数
        
		else{
			for(int z=1;z<=3;z++){
				if(z!=t1&&z!=op){   //注意这里不能与输入的数相同
					cout<<z<<' ';
					break;
				}
			}
			cnt2++;
			cout<<a2[cnt2].x<<' '<<a2[cnt2].y<<endl;
		}
        //红色块填满了就往蓝色块填可行数
        
	}
	return 0;
}
posted @ 2022-09-29 19:04  Binary_Lee  阅读(18)  评论(0编辑  收藏  举报
Title