火力网加强版(difficult)

来源:互联网 发布:java todo怎么用 编辑:程序博客网 时间:2024/04/27 19:06

火力网加强版(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;  }