火力网加强版(difficult)
Time Limit:1000MS Memory Limit:65536K
Total Submit:32 Accepted:12
Description
假定我们有一个正方形的城市,拥有笔直的街道。城市由n行n列正方形的地块组成,每一块表示为一个街道或一堵墙。
碉堡就是一个小的城堡,有四个用于射击的口子。这四个口子分别朝着东、南、西、北方向。每一个口子都有一个用于射击的机关枪。
我们假定子弹力量很大,足以射到任何距离,并且破坏线路上的碉堡。另一方面,一堵墙非常牢固可以挡住子弹。
我们的目标就是在城市上放置一些碉堡,使得没有两个碉堡可以互相破坏。碉堡的合法配置就是没有两个碉堡在同一行或同一列上,除非它们之间至少有一堵墙隔在中间。在题目中我们考虑小的正方形城市(最多4×4)包含墙,使得子弹不能穿越。
下面的图示表示同一个区域,第一个图为空图,第二个和第三个图表示合法的配置,第四个图和第五个图表示违法的配置。对这个区域而言,合法配置的最大的碉堡的数量为5,第二个图显示了一种配置的方法,但还有另外的方法。
你的任务就是编程,对于给出的地图,计算碉堡的最大数量,可以合法配置在城市中。
Input
输入的第一行为n表示一个地图的大小,n最多为10,下面n行表示地图的每一列,一个‘.’表示空地,‘X’表示墙。
Output
输出一个最大的碉堡数量,使得在城市中可以合法配置。
Sample Input
4
.X..
....
XX..
....
Sample Output
5
#include<iostream> using namespace std; bool used[100];int a[100][100],p[100],re[100],b[100][100],c[100][100]; int t,tot; bool find(int x) { int j; for(j=1;j<=t;j++) { if(a[x][j]&&used[j]!=1) { used[j]=1; if(p[j]==false||find(p[j])) { p[j]=x; return true; } } } return false; } int main() { int n,l=0;char x,y; cin>>n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { cin>>x; if(x=='.')b[i][j]=0; else b[i][j]=-1; } for(int i=1;i<=n;i++) { int j=1; if(b[i][j]!=-1)l++; while(j<=n) { if(b[i][j]==0)b[i][j]=l; else { while(b[i][j]==-1)j++; l++; b[i][j]=l; } j++; } } int k=0; for(int i=1;i<=n;i++) { int j=1; if(b[j][i]!=-1)t++; while(j<=n) { if(b[j][i]>0)c[j][i]=t; else { while(b[j][i]==-1) { c[j][i]=-1; j++; } t++; c[j][i]=t; } j++; } } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(b[i][j]!=-1&&c[i][j]!=-1)a[b[i][j]][c[i][j]]=true; int ans=0; for(int i=1;i<=l;i++) { for(int j=1;j<=t;j++)used[j]=false; if(find(i))ans++; } cout<<ans; }