FZU1686--神龍的難題(Dancing Links)

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
思路:每次攻擊是一個小矩形的範圍傷害。枚舉n*m個矩形。轉換爲求最少的矩形的並使得所有怪物都被覆蓋。
顯然就是Dancing Links 解決重複覆蓋的問題了。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int MaxM = 15*15+10;
const int MaxN = 15*15+10;
const int maxnode = MaxN * MaxM;
const int INF = 0x3f3f3f3f;
struct DLX
{
    int n,m,size;
    int U[maxnode],D[maxnode],R[maxnode],L[maxnode],Row[maxnode],Col[maxnode];
    int H[MaxN],S[MaxM];
    int ansd;
    void init(int _n,int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0;i <= m;i++)
        {
            S[i] = 0;
            U[i] = D[i] = i;
            L[i] = i-1;
            R[i] = i+1;
        }
        R[m] = 0; L[0] = m;
        size = m;
        for(int i = 1;i <= n;i++)H[i] = -1;
    }
    void Link(int r,int c)
    {
        ++S[Col[++size]=c];
        Row[size] = r;
        D[size] = D[c];
        U[D[c]] = size;
        U[size] = c;
        D[c] = size;
        if(H[r] < 0)H[r] = L[size] = R[size] = size;
        else
        {
            R[size] = R[H[r]];
            L[R[H[r]]] = size;
            L[size] = H[r];
            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 resume(int c)
    {
        for(int i = U[c];i != c;i = U[i])
            L[R[i]] = R[L[i]] = i;
    }
    bool v[MaxM];
    int f()
    {
        int ret = 0;
        for(int c = R[0]; c != 0;c = R[c])v[c] = true;
        for(int c = R[0]; c != 0;c = R[c])
            if(v[c])
            {
                ret++;
                v[c] = false;
                for(int i = D[c];i != c;i = D[i])
                    for(int j = R[i];j != i;j = R[j])
                        v[Col[j]] = false;
            }
        return ret;
    }
    void Dance(int d)
    {
        if(d + f() >= ansd)return;
        if(R[0] == 0)
        {
            if(d < ansd)ansd = d;
            return;
        }
        int c = R[0];
        for(int i = R[0];i != 0;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])resume(j);
            resume(i);
        }
    }
};
DLX g;

struct GW
{
	int r,c;
}gw[18*18];
int vis[18][18];
int main()
{
	//freopen("in.txt","r",stdin);
	int n,m;
	while(scanf("%d%d",&n,&m)==2)
	{
		int fuck = 0;
		for(int i = 1;i <= n;i++)
		{
			for(int j = 1;j <= m;j++)
			{
				scanf("%d",&vis[i][j]);
				if(vis[i][j])	
				{
					fuck++;	gw[fuck].r = i;	gw[fuck].c = j;
				}
			}
		}
		int n1,m1;	scanf("%d%d",&n1,&m1);
		if(fuck<1)	
		{
			cout << 0 << endl;
			continue;
		}
		g.init(n*m,fuck);
		for(int i = 1;i <= n;i++)
		{
			for(int j = 1;j <= m;j++)
			{
				int pos = (i-1)*m+j;
				for(int k = 1;k <= fuck;k++)
				{
					if(i <= gw[k].r && i+n1 > gw[k].r && j <= gw[k].c && j+m1 > gw[k].c)
						g.Link(pos,k);
				}
			}
		}
		g.ansd = INF;
		g.Dance(0);
		printf("%d\n",g.ansd);
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章