题意:一个农夫想为一个有低洼地区的草地铺木板,木板的长度不定,宽度为1格,铺下的木板不能盖到任何一处草地,问至少需要多少木板。

解题思路:这题想了很久,一直想不出来,可能最近的是失恋导致的效率问题。这题的构图十分精妙,就例子来说,
给出的草地是
*.*.
.***
***.
..*.
假设只   横  着放木板的话,我们把木板编个号
1.2.
.333
444.
..5.
假设只   竖  着放木板的话,我们把木板编个号
1.4.
.345
234.
..4.
那么现在对于每个低洼地区,要么被不同的横木板覆盖,要么被不同的竖木板覆盖,而所有低洼地区只要被覆盖一遍就行了,所以我们对横竖木板进行建立二部图,当某一横木板与某一竖木板有共同覆盖区域时(注意横木板不可能与横木板有共同覆盖区,竖木板也是),就加一条边,那么问题变为求这个二部图的最小点覆盖集了。

这题数组开大一点...开到900以上吧

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

int x,y,mj[1005][1005],n,m,c[1005][1005],r[1005][1005],result[1005],flag[1005],p,ans;
char mjc[1005][1005];

bool find(int i)
{
 int j;
 for(j=1;j<=p;j++)
 {
  if(mj[i][j]!=0&&flag[j]==0)
  {
   flag[j]=1;
   if(result[j]==0||find(result[j]))
   {
    result[j]=i;
    return 1;
   }
  }
 }
 return 0;
}

 

 

int main()
{
 int i,j,f;
 while(scanf("%d %d",&n,&m)!=EOF)
 {
  memset(mj,0,sizeof(mj));
  memset(result,0,sizeof(result));
  memset(c,0,sizeof(c));
  memset(r,0,sizeof(r));
  getchar();
  for(i=1;i<=n;i++)
  {
   for(j=1;j<=m;j++)
    mjc[i][j]=getchar();
   getchar();
  }
  int q=0;
  for(j=1;j<=m;j++)
  {
   f=0;
   for(i=1;i<=n;i++)
   {
    if(mjc[i][j]=='*')
    {
     if(f==0){q++;f=1;c[i][j]=q;}
     else
     {
      c[i][j]=q;
     }
    }
    else
    {
     c[i][j]=0;
     f=0;
    }
   }
  }

  p=0;
  for(i=1;i<=n;i++)
  {
   f=0;
   for(j=1;j<=m;j++)
   {
    if(mjc[i][j]=='*')
    {
     if(f==0){p++;f=1;r[i][j]=p;}
     else
     {
      r[i][j]=p;
     }
    }
    else
    {
     r[i][j]=0;
     f=0;
    }
   }
  }

  for(i=1;i<=n;i++)
   for(j=1;j<=m;j++)
    mj[c[i][j]][r[i][j]]=1;
  ans=0;
  for(i=1;i<=q;i++)
  {
   memset(flag,0,sizeof(flag));
   if(find(i)) ans++;
  }
  printf("%d\n",ans);

 }


}