题解
直接连边然后做最小路径覆盖
最小路径覆盖=原图点数-新图最大匹配数
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int>e[2500<<2];
int n,m,r,c,cnt,mark,vis[51*51],lnk[51*51],map[55][55];
inline void add(int x,int y,int nx,int ny){
if(nx<1||ny<1||nx>n||ny>m||!map[nx][ny]) return;
e[map[x][y]].push_back(map[nx][ny]);
}
inline bool dfs(int x){
for(int i=0;i<e[x].size();++i)
if(vis[e[x][i]]!=mark){
vis[e[x][i]]=mark;
if(!lnk[e[x][i]]||dfs(lnk[e[x][i]])){
lnk[e[x][i]]=x;
return 1;
}
}
return 0;
}
int main(){
scanf("%d%d%d%d",&n,&m,&r,&c);
for(int i=1;i<=n;++i){
char ch[55];
scanf("%s",ch+1);
for(int j=1;j<=m;++j)
if(ch[j]=='x') map[i][j]=0;
else map[i][j]=++cnt;
}
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(map[i][j]){
add(i,j,i+r,j+c);
add(i,j,i+r,j-c);
add(i,j,i+c,j+r);
add(i,j,i+c,j-r);
}
int ans=0;
for(int i=1;i<=cnt;++i){
++mark;
ans+=dfs(i);
}
printf("%d\n",cnt-ans);
return 0;
}