输入样例:
6
1 7
0 0
1 2
2 0
1 4
3 4
输出样例:
1
样例解释
y=0,x=1,y=4 可满足将所有奶牛位置覆盖。
题解(DFS)
-
首先选择一个点,他有两种选择,用x或者y方向的线,
-
选择方向后,将此方向的所有点给删除
-
然后将未删除的点中随机选一个,再区分x或y方向,重复第2步
-
然后重复第三步
-
前四步完成后,删除的点就分别有三条线穿过了,此时判断是否还有剩下的即可得出结果
-
若还有剩下点说明此方案不成立,则回溯旋转不同方向
-
如此一共有8种选择线的方向组合,如下图
代码思路:
-
用dfs递归三层来实现
-
用一个Struct来装坐标和记录点是否删除的状态
-
用数组来记录所有点
-
为了防止每次都遍历数组判断点是否删除,每次一层遍历的起点是新的线决定点,前面所有的点都被删除了(也就是已经有线穿过),起点之后的点在数组中包含了删除与未删除的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unordered_map>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 50010;
struct Node{
int x,y,status;
}node[N];
int n;
int dfs(int index, int level){
if(level == 0){
if(index != n) return 0;
else return 1;
}
int next = n;
node[index].status = 1;
// try x line
for(int i = index+1;i<n;i++){
if(node[i].x == node[index].x){
node[i].status = 1;
}else if(node[i].status){
continue;
}else{
next = i;
break;
}
}
for(int i = next+1;i<n;i++){
if(node[i].x == node[index].x){
node[i].status = 1;
}else if(node[i].status){
continue;
}
}
int ret = dfs(next,level-1);
for(int i = index+1;i<n;i++){ // 回溯
if(node[i].x == node[index].x){
node[i].status = 0;
}
}
// try y line
next = n;
for(int i = index+1;i<n;i++){
if(node[i].y == node[index].y){
node[i].status = 1;
}else if(node[i].status){
continue;
}else{
next = i;
break;
}
}
for(int i = next+1;i<n;i++){
if(node[i].y == node[index].y){
node[i].status = 1;
}else if(node[i].status){
continue;
}
}
ret = dfs(next,level-1) or ret;
for(int i = index;i<n;i++){ // 回溯
if(node[i].y == node[index].y){
node[i].status = 0;
}
}
return ret;
}
int main(){
cin>>n;
for(int i = 0;i<n;i++){
cin>>node[i].x>>node[i].y;
node[i].status = 0;
}
cout<<dfs(0,3)<<endl;
return 0;
}