您的位置:首页 > 其它

DLX(重复覆盖)FZU1686神龙的难题

2014-09-30 22:21 316 查看
FZU - 1686

神龙的难题

Time Limit: 1000MS

Memory Limit: 32768KB

64bit IO Format: %I64d & %I64u

[Submit] [Go
Back] [Status]

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

思路:因为要消灭所有的敌人,也就是覆盖矩阵中所有的1,所以多所有的1编号,然后这些当做列,然后每个位置当做行,他有影响的范围,对应1对应的编号的列

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int INF=1000000000;
const int maxn=15*15+10;
const int maxm=15*15+10;
const int maxnode=maxn*maxm;
int N,M,n,m;
int id[20][20];
struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode];
    int H[maxn],S[maxm];
    int row[maxnode],col[maxnode];
    int ansd,ans[maxn];
    bool vis[maxnode];
    void init(int N,int M)
    {
        n=N,m=M;
        ansd=INF;
        for(int i=0;i<=m;i++)
        {
            S[i]=0;
            U[i]=D[i]=i;
            L[i]=i-1;
            R[i]=i+1;
        }
        L[0]=m,R[m]=0;
        size=m;
        for(int i=0;i<=n;i++)H[i]=-1;
    }
    void Link(int r,int c)
    {
        ++S[col[++size]=c];
        row[size]=r;
        D[size]=D[c];
        U[size]=c;
        U[D[c]]=size;
        D[c]=size;
        if(H[r]<0)H[r]=R[size]=L[size]=size;
        else
        {
            R[size]=R[H[r]];
            L[size]=H[r];
            L[R[H[r]]]=size;
            R[H[r]]=size;
        }
    }
    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 restore(int c)
    {
        for(int i=U[c];i!=c;i=U[i])
            L[R[i]]=R[L[i]]=i;
    }
    int f()
    {
        int cnt=0;
        for(int i=R[0];i;i=R[i])vis[i]=0;
        for(int c=R[0];c;c=R[c])
        {
            if(!vis[c])
            {
                cnt++;vis[c]=1;
                for(int i=D[c];i!=c;i=D[i])
                    for(int j=R[i];j!=i;j=R[j])
                        vis[col[j]]=1;
            }
        }
        return cnt;
    }
    void Dance(int d)
    {
        if(d+f()>=ansd)return;
        if(R[0]==0)
        {
            if(ansd>d)ansd=d;
            return;
        }
        int c=R[0];
        for(int i=R[0];i;i=R[i])
            if(S[i]<S[c])c=i;
        for(int i=D[c];i!=c;i=D[i])
        {
            remove(i);
            for(int j=R[i];j!=i;j=R[j])remove(j);
            Dance(d+1);
            for(int j=L[i];j!=i;j=L[j])restore(j);
            restore(i);
        }
    }
}dlx;
int main()
{
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        int sz=0;
        memset(id,0,sizeof(id));
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
            {
                int x;
                scanf("%d",&x);
                if(x)id[i][j]=++sz;
            }
        dlx.init(N*M,sz);
        sz=1;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=N;i++)
            for(int j=1;j<=M;j++)
            {
                for(int x=0;i+x<=N&&x<n;x++)
                    for(int y=0;j+y<=M&&y<m;y++)
                        if(id[i+x][j+y])
                            dlx.Link(sz,id[i+x][j+y]);
                sz++;
            }
        dlx.Dance(0);
        printf("%d\n",dlx.ansd);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: