题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2150
思路:很裸的最小路径覆盖问题,这个问题有两种解法:1、网络流,拆点,2、二分图最大匹配
将每个无障碍的点和它可达的无障碍的点连边,然后跑二分图最大匹配即可。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <queue> #define MAXE 7000000 #define MAXN 2600 using namespace std; struct edge { int u,v,next; }edges[MAXE]; char map[55][55]; int n,m,r,c; int head[MAXN],nCount=0; int linky[MAXN]; bool visit[MAXN]; bool inMap(int x,int y) { if(x<1||x>n||y<1||y>m) return false; if(map[x][y]=='x') return false; return true; } int getNum(int x,int y) { return (x-1)*m+y; } void AddEdge(int U,int V) { edges[++nCount].u=U; edges[nCount].v=V; edges[nCount].next=head[U]; head[U]=nCount; } bool dfs(int u) { for(int p=head[u];p!=-1;p=edges[p].next) { int v=edges[p].v; if(visit[v]) continue; visit[v]=true; if(linky[v]==-1||dfs(linky[v])) { linky[v]=u; return true; } } return false; } int main() { int i,j; memset(head,-1,sizeof(head)); scanf("%d%d%d%d",&n,&m,&r,&c); for(i=1;i<=n;i++) { char in[MAXN]; scanf("%s",in+1); for(j=1;j<=m;j++) map[i][j]=in[j]; } for(i=1;i<=n;i++) for(j=1;j<=m;j++) if(map[i][j]=='.') { if(inMap(i-c,j-r)) AddEdge(getNum(i-c,j-r),getNum(i,j)); if(inMap(i-c,j+r)) AddEdge(getNum(i-c,j+r),getNum(i,j)); if(inMap(i-r,j-c)) AddEdge(getNum(i-r,j-c),getNum(i,j)); if(inMap(i-r,j+c)) AddEdge(getNum(i-r,j+c),getNum(i,j)); } memset(linky,-1,sizeof(linky)); int ans=0,sum=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if(map[i][j]=='.') { memset(visit,false,sizeof(visit)); ans+=dfs(getNum(i,j)); sum++; } } printf("%d\n",sum-ans); return 0; }