FZU 1686 DLX建图重复覆盖

Problem 1686 神龙的难题

Accept: 394    Submit: 1255

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

把每一个怪物编号,然后枚举矩形左上角,扫描矩形内的怪物编号建图,行为矩形的左上角编号,列为怪物编号,模型转化为选取最少的矩形将列上的怪物覆盖,很明显的

dlx重复覆盖。

代码:

/* ***********************************************
Author :_rabbit
Created Time :2014/4/29 16:17:31
File Name :9.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
struct DLX{
    const static int maxn=2010;
    #define FF(i,A,s) for(int i = A[s];i != s;i = A[i])
    int L[maxn],R[maxn],U[maxn],D[maxn];
    int size,col[maxn],row[maxn],s[maxn],H[maxn];
    bool vis[2010];
	int ans[maxn],cnt;
    void init(int m){
        for(int i=0;i<=m;i++){
            L[i]=i-1;R[i]=i+1;U[i]=D[i]=i;s[i]=0;
        }
        memset(H,-1,sizeof(H));
        L[0]=m;R[m]=0;size=m+1;
    }
	void link(int r,int c){
         U[size]=c;D[size]=D[c];U[D[c]]=size;D[c]=size;
         if(H[r]<0)H[r]=L[size]=R[size]=size;
         else {
             L[size]=H[r];R[size]=R[H[r]];
             L[R[H[r]]]=size;R[H[r]]=size;
         }
         s[c]++;col[size]=c;row[size]=r;size++;
     }
	void del(int c){//精确覆盖
        L[R[c]]=L[c];R[L[c]]=R[c];
        FF(i,D,c)FF(j,R,i)U[D[j]]=U[j],D[U[j]]=D[j],--s[col[j]];
    }
    void add(int c){  //精确覆盖
        R[L[c]]=L[R[c]]=c;
        FF(i,U,c)FF(j,L,i)++s[col[U[D[j]]=D[U[j]]=j]];
    }
	bool dfs(int k){//精确覆盖
        if(!R[0]){
            cnt=k;return 1;
        }
        int c=R[0];FF(i,R,0)if(s[c]>s[i])c=i;
        del(c);
        FF(i,D,c){
            FF(j,R,i)del(col[j]);
            ans[k]=row[i];if(dfs(k+1))return true;
            FF(j,L,i)add(col[j]);
        }
        add(c);
        return 0;
    }
    void remove(int c){//重复覆盖
        FF(i,D,c)L[R[i]]=L[i],R[L[i]]=R[i];
    }
     void resume(int c){//重复覆盖
         FF(i,U,c)L[R[i]]=R[L[i]]=i;
     }
    int A(){//估价函数
        int res=0;
        memset(vis,0,sizeof(vis));
        FF(i,R,0)if(!vis[i]){
                res++;vis[i]=1;
                FF(j,D,i)FF(k,R,j)vis[col[k]]=1;
            }
        return res;
    }
    void dfs(int now,int &lim){//重复覆盖
        if(R[0]==0)lim=min(lim,now);
        else if(now+A()<lim){
            int temp=INF,c;
            FF(i,R,0)if(temp>s[i])temp=s[i],c=i;
            FF(i,D,c){
                remove(i);FF(j,R,i)remove(j);
                dfs(now+1,lim);
                FF(j,L,i)resume(j);resume(i);
            }
        }
    }
}dlx;
int main()
{
	int n,m,rr,cc,mp[20][20],x,n1,m1;
    while(~scanf("%d%d",&n,&m)){
        cc = 0;rr = 0 ;
        memset(mp,0,sizeof(mp));
        for(int i = 1 ; i <= n ; i ++ )
            for(int j = 1 ; j <= m ; j++ ){
                scanf("%d",&x);
                if(x == 1 )mp[i][j] = ++ cc;
                else mp[i][j] = 0 ;
            }

        dlx.init(cc);
        scanf("%d%d",&n1,&m1);
        for(int i = 1 ; i<= n - n1 + 1 ; i ++ )
            for(int j = 1 ; j <= m - m1 + 1; j ++ )
            {
                rr ++ ;
                for(int i1 = i ; i1 <= i + n1 - 1 ; i1 ++ )
                    for(int j1 = j ; j1 <= j + m1 - 1 ; j1 ++ )
                        if(mp[i1][j1] != 0 )
                          dlx.link(rr,mp[i1][j1]);
            }
        int ans = n * m;
        dlx.dfs(0,ans);
        printf("%d\n",ans);

    }
    return 0;
}

FZU 1686 DLX建图重复覆盖,码迷,mamicode.com

时间: 2024-11-01 19:05:29

FZU 1686 DLX建图重复覆盖的相关文章

FZU 1686 神龙的难题(重复覆盖问题&amp;舞蹈链)

题目链接:[kuangbin带你飞]专题三 Dancing Links D - 神龙的难题 题意 Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉就是这样的一个人.她骑着她的坐骑,神龙米格拉一起消灭干扰人类生存的魔物,维护王国的安定.艾米莉希望能够在损伤最小的前提下完成任务.每次战斗前,她都用时间

FZU 1686 神龙的难题 重复覆盖

转换成0,1模型就好了,注意数据范围 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h

FZU 1686 龙之谜 重复覆盖

兑换0,1模型,如.注意,数据的范围 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <math.h

FZU 1686 舞蹈链之可重复覆盖

点击打开链接 题意:中文题了 思路:做了几个舞蹈链的题目了,第一感觉总会想到去用网络流去写,哎YY一会就是错的,乖乖用舞蹈链来写把,对于这道题目我们可以将所有的1看成是列,然后行则是一个一个的小矩阵,每一行也就是小矩阵连接自己可以消灭的1,但是首先要给所有的1编一下号,再然后就是模版舞蹈链了 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #includ

FZU 2165 v11(最小重复覆盖)

告诉你若干个(<=100)武器的花费以及武器能消灭的怪物编号,问消灭所有怪物(<=100)的最小花费...当然每个武器可以无限次使用,不然这题就太水了╮(╯▽╰)╭ 这题当时比赛的时候连题都还没看就结束了....赛后一看,果断是重复覆盖... 不过之后一直没敲...然后今天算是补回来吧,同时也把好久以前学的DLX复习一下... DLX的话,双向十字链表...具体的话,百度Google什么的dancing links... 一开始敲的时候还是挺顺利的,因为之前做过几次重复覆盖都是直接拿精确覆盖的

[DLX重复覆盖] fzu 1686 神龙的难题

题意: 中文题 思路: 想到是一个重复覆盖的问题,然后就是最少放多少个能覆盖满. 建图的话就是先标记一下哪些点有怪物,最多就是n*m个怪物. 然后就是行. 行的话就看输入的x和y能框住多少的范围了. 然后四重循环遍历一遍建边就ok了. 代码: #include"stdio.h" #include"algorithm" #include"string.h" #include"iostream" #include"cma

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

FZU 1686 神龙的难题 题目链接 题意:中文题 思路:每一个1看成列,每个位置作为左上角的矩阵看成行,dlx重复覆盖即可 代码: #include <cstdio> #include <cstring> using namespace std; const int MAXNODE = 66666; const int INF = 0x3f3f3f3f; const int MAXM = 230; const int MAXN = 230; int K; struct DLX

FZU 1686 神龙的难题 DLX重复覆盖

DLX重复覆盖: 需要一个A*函数剪支 Problem 1686 神龙的难题 Accept: 462    Submit: 1401 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会进入城市附近,干扰人民的生活.就要有一些人出来守护居民们不被魔物侵害.魔法使艾米莉

(简单) FZU 1686 神龙的难题 , DLX+可重复覆盖。

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