FZU 1686 神龙的难题 [DLX] [RepeatCover]

神龙的难题
Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u

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

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

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

Sample Input
4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
2 2
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
2 2

Sample Output
4
1

Source
FOJ月赛-2009年2月- TimeLoop


这个题的话,每次用一个小矩阵去框,把里面的1都变成0,这是一次操作。
那么就可以转化成01重复覆盖了。
remove()稍微有一些不一样,只需要把这行包含1的列都从水平链表中删除。
另外,Dance(d+1)的时候不用return,因为需要找出最少的步数。
用A*估价函数增速,因为H() < H’(),所以这个是可行的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
const int INF=0x3f3f3f3f;
const int maxn = 230;
struct Node
{
    int left,right,up,down;
    int col,row;
}node[maxn*maxn];
#define left(x) node[x].left
#define right(x) node[x].right
#define up(x) node[x].up
#define down(x) node[x].down
#define col(x) node[x].col
#define row(x) node[x].row
int maxnode;
int rows,cols;
int head;
int tot[maxn];
inline void disable_row(int root)
{
    left(right(root)) = left(root);
    right(left(root)) = right(root);
}
inline void disable_col(int root)
{
    up(down(root)) = up(root);
    down(up(root)) = down(root);
}
inline void enable_row(int root)
{
    left(right(root)) = root;
    right(left(root)) = root;
}
inline void enable_col(int root)
{
    up(down(root)) = root;
    down(up(root)) = root;
}
inline void remove(int root)
{
    for(int i=down(root);i^root;i=down(i))
        disable_row(i);
}
inline void restore(int root)
{
    for(int i=up(root);i^root;i=up(i))
        enable_row(i);
}
void initialize()
{
    memset(node,0,sizeof(node));
    memset(tot,0,sizeof(tot));
    rows=0; cols=maxnode; // maxnode for the monsters exists
    head=0;
    right(head)=1; left(head)=cols;
    for(int i=1;i<=cols;i++)
    {
        left(i) = i-1;
        right(i) = i+1;
        up(i) = i;
        down(i) = i;
        row(i) = 0;
        col(i) = i;
    }
    right(cols) = head;
}
int ans;
bool vis[maxn];
inline int h()
{
    int cnt = 0;
    for(int i=right(head);i^head;i=right(i)) vis[i]=false;
    for(int i=right(head);i^head;i=right(i))
    {
        if(vis[i]) continue;
        vis[i] = true; cnt++;
        for(int j=down(i);j^i;j=down(j))
            for(int k=right(j);k^j;k=right(k))
                vis[col(k)] = true;
    }
    return cnt;
}
void Dance(int d)
{
    if(d+h()>=ans) return ;
    int c1 = right(head);
    if(c1 == head)
    {
        smin(ans,d);
        return;
    }
    for(int i=right(c1);i^head;i=right(i))
        if(tot[i]<tot[c1]) c1 = i;
    if(!tot[c1]) return;
    for(int i=down(c1);i^c1;i=down(i))
    {
        remove(i);
        for(int j=right(i);j^i;j=right(j)) remove(j);
        Dance(d+1); // not need to return if true 'coz the cases are still remaining to be judged
        for(int j=left(i);j^i;j=left(j)) restore(j);
        restore(i);
    }
}
int a[maxn];
void add_row(int cnt)
{
    rows++;
    for(int i=1;i<=cnt;i++)
    {
        maxnode++;
        if(i==1)
        {
            left(maxnode) = maxnode;
            right(maxnode) = maxnode;
        }
        else
        {
            left(maxnode) = maxnode-1;
            right(maxnode) = right(maxnode-1);
            enable_row(maxnode);
        }
        up(maxnode) = up(a[i]);
        down(maxnode) = a[i];
        enable_col(maxnode);
        row(maxnode) = rows;
        col(maxnode) = a[i];
        tot[a[i]]++;
    }
}
int n,m;
int g[20][20],id[20][20];
int n1,m1;
bool init()
{
    if(!~scanf("%d%d",&n,&m)) return false;
    memset(g,0,sizeof(g));
    memset(id,0,sizeof(id));
    maxnode = 0; // of great significance!!
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&g[i][j]);
            if(g[i][j]) id[i][j] = ++maxnode;
        }
    scanf("%d%d",&n1,&m1);
    initialize();
    ans=INF;
    for(int i=1;i<=n-n1+1;i++)
        for(int j=1;j<=m-m1+1;j++)
        {
            int cnt=0;
            for(int x=0;x<n1;x++)
                for(int y=0;y<m1;y++)
                    if(g[i+x][j+y]) a[++cnt] = id[i+x][j+y];
            if(cnt) add_row(cnt);
        }
    return true;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("dragon.in","r",stdin);
    freopen("dragon.out","w",stdout);
#endif
    while(init())
    {
        Dance(0);
        printf("%d\n",ans);
    }
    return 0;
}

原创文章 152 获赞 15 访问量 6万+

猜你喜欢

转载自blog.csdn.net/ourfutr2330/article/details/52777326