fzu 1686 重复覆盖

来源:互联网 发布:剑侠情缘3男捏脸数据 编辑:程序博客网 时间:2024/06/03 17:22
Problem 1686 神龙的难题

Accept: 460    Submit: 1397
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间停止魔法停住时间,然后米格拉他就可以发出火球烧死敌人.米格拉想知道,他如何以最快的速度消灭敌人,减轻艾米莉的负担.

Input

数据有多组,你要处理到EOF为止.每组数据第一行有两个数,n,m,(1<=n,m<=15)表示这次任务的地区范围.然后接下来有n行,每行m个整数,如为1表示该点有怪物,为0表示该点无怪物.然后接下一行有两个整数,n1,m1 (n1<=n,m1<=m)分别表示米格拉一次能攻击的行,列数(行列不能互换),假设米格拉一单位时间能发出一个火球,所有怪物都可一击必杀.

Output

输出一行,一个整数,表示米格拉消灭所有魔物的最短时间.

Sample Input

4 41 0 0 10 1 1 00 1 1 01 0 0 12 24 4 0 0 0 00 1 1 00 1 1 00 0 0 02 2

Sample Output

41

Source

FOJ月赛-2009年2月- TimeLoop
//把每个魔物当成一列,每个小矩阵当成一行,覆盖到的魔物标为1,构造01阵,dancing links解决#include<stdio.h>#include<string.h>#define N 160000#define M 400#define inf 0x3fffffffint len,size,u[N],d[N],l[N],r[N],row[N],col[N];int a[20][20],s[M],h[M],vis[M];//开小点不然超内存,破oj,居然显示超时,我还以为模板有问题呢,坑。void init(int n,int m){  int i;   for(i=0;i<=m;i++)   {      s[i]=0;      d[i]=u[i]=i;      l[i]=i-1;      r[i]=i+1;   }   l[0]=m; r[m]=0; size=m;   for(i=1;i<=n;i++)     h[i]=-1;}void link(int x,int y){     ++s[col[++size]=y];     row[size]=x;     u[d[y]]=size;     d[size]=d[y];     d[y]=size;     u[size]=y;     if(h[x]<0)      h[x]=l[size]=r[size]=size;     else     {        l[r[h[x]]]=size;        r[size]=r[h[x]];        r[h[x]]=size;        l[size]=h[x];     }}void remove(int c){   for(int i=d[c];i!=c;i=d[i])     l[r[i]]=l[i],r[l[i]]=r[i];}void resume(int c){    for(int i=u[c];i!=c;i=u[i])       l[r[i]]=r[l[i]]=i;}int f(){   int i,j,k,num=0;   memset(vis,0,sizeof(vis));   for(i=r[0];i!=0;i=r[i])   {      if(!vis[i])      {         num++;         for(j=d[i];j!=i;j=d[j])            for(k=r[j];k!=j;k=r[k])              vis[col[k]]=1;      }   }   return num;}void dance(int x){   int c,i,j;    if(x+f()>=len)//减枝      return ;    if(r[0]==0)    {      if(x<len) len=x;       return ;    }    c=r[0];    for(i=r[0];i!=0;i=r[i])      if(s[i]<s[c])        c=i;    for(i=d[c];i!=c;i=d[i])    {        remove(i);       for(j=r[i];j!=i;j=r[j]) remove(j);        dance(x+1);       for(j=l[i];j!=i;j=l[j])  resume(j);       resume(i);    }}int main(){  int n,m,i,j,k,p,num,x,y,ans;  //freopen("a.txt","r",stdin);  while(scanf("%d%d",&n,&m)!=EOF)  {     num=0;     for(i=1;i<=n;i++)       for(j=1;j<=m;j++)         {           scanf("%d",&a[i][j]);           if(a[i][j]==1)              a[i][j]=++num;         }    init(n*m,num);    scanf("%d%d",&x,&y);    ans=1; len=inf;    for(i=1;i<=n;i++)    {      for(j=1;j<=m;j++)      {        for(k=0;k<x&&i+k<=n;k++)//判断边界,不然超时        {          for(p=0;p<y&&j+p<=m;p++)            if(a[i+k][j+p])              link(ans,a[i+k][j+p]);        }        ans++;      }    }    dance(0);    printf("%d\n",len);  }  return 0;}



0 0
原创粉丝点击