题目链接:Farm Irrigation
如左图所示,有11种管道,问给定一个图,最少要挖几个井才能灌溉到所有的管道
如右图,至少需要三个井口
两种做法DFS和并查集
难点在管道接口的判断:将一个块变成四个点,有管道伸出就是1,否则就为0
判断两个块是否在该方向管道是想通的 用&就可以了
int pipe[][4]={
{1,0,1,0},
{1,0,0,1},
{0,1,1,0},
{0,1,0,1},
{1,1,0,0},
{0,0,1,1},
{1,0,1,1},
{1,1,1,0},
{0,1,1,1},
{1,1,0,1},
{1,1,1,1}
};
DFS代码:
#include <stdio.h>
#include <memory.h>
#include <iostream>
using namespace std;
const int maxn=55;
int pipe[][4]={
{1,0,1,0},
{1,0,0,1},
{0,1,1,0},
{0,1,0,1},
{1,1,0,0},
{0,0,1,1},
{1,0,1,1},
{1,1,1,0},
{0,1,1,1},
{1,1,0,1},
{1,1,1,1}
};
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
char str[maxn][maxn];
int g[maxn][maxn];
bool vis[maxn][maxn];
int m,n;
bool check(int x,int y)
{
if(x<0||y<0||x>m-1||y>n-1)return false;
if(vis[x][y])return false;
return true;
}
void dfs(int x,int y)
{
for(int i=0;i<4;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(check(nx,ny)){
if(pipe[g[x][y]][i]&&pipe[g[nx][ny]][i^1]){
vis[nx][ny]=true;
dfs(nx,ny);
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int ans;
while(scanf("%d%d",&m,&n)!=EOF&&m>0&&n>0){
for(int i=0;i<m;i++){
scanf("%s",str[i]);
for(int j=0;j<n;j++){
g[i][j]=str[i][j]-'A';
}
}
memset(vis,0,sizeof(vis));
ans=0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(!vis[i][j]){
vis[i][j]=true;
dfs(i,j);
ans++;
}
}
}
printf("%d\n",ans);
}
return 0;
}
并查集代码:
#include <stdio.h>
#include <memory.h>
#include <iostream>
using namespace std;
const int maxn=55;
int pipe[][4]={
{1,0,1,0},
{1,0,0,1},
{0,1,1,0},
{0,1,0,1},
{1,1,0,0},
{0,0,1,1},
{1,0,1,1},
{1,1,1,0},
{0,1,1,1},
{1,1,0,1},
{1,1,1,1}
};
int m,n;
int g[maxn][maxn];
int F[maxn*maxn+5];
void init()
{
int tot=m*n;
for(int i=0;i<tot;i++)F[i]=i;
}
int id(int x,int y)
{
return x*n+y;
}
int Find(int x)
{
int r=x,tmp;
while(F[x]!=x)x=F[x];
while(r!=x){
tmp=F[r];
F[r]=x;
r=tmp;
}
return x;
}
void Unit(int x,int y)
{
int t1=Find(x);
int t2=Find(y);
if(t1!=t2)F[t1]=F[t2];
}
int main()
{
//freopen("in.txt","r",stdin);
int ans,id1,id2,id3;
char str[maxn];
while(scanf("%d%d",&m,&n)!=EOF&&m>0&&n>0){
ans=0;
init();
for(int i=0;i<m;i++){
scanf("%s",str);
for(int j=0;j<n;j++){
g[i][j]=str[j]-'A';
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
id1=id(i,j);
if(i+1<m){
id2=id(i+1,j);
if(pipe[g[i][j]][1]&&pipe[g[i+1][j]][0])
Unit(id1,id2);
}
if(j+1<n){
id3=id(i,j+1);
if(pipe[g[i][j]][3]&&pipe[g[i][j+1]][2])
Unit(id1,id3);
}
}
}
int tot=m*n;
for(int i=0;i<tot;i++)
if(F[i]==i)
ans++;
printf("%d\n",ans);
}
return 0;
}