FZU 1686(重复覆盖)

题目连接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=31370

题意:用尽量少r*c的小矩形覆盖大矩形n*m中的所有1,将所有1转换成size列,然后以大矩形的每点当成小矩形r*c的左上角覆盖到的1当成一行,问题则转换成m*n行中选尽量少的行来覆盖所有列。。。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxnode=250010;
const int MaxN=510;
const int MaxM=510;
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,ans[MaxN];
    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 vis[maxnode];
    int h()
    {
        int res=0;
        for(int c=R[0];c!=0;c=R[c])vis[c]=true;
        for(int c=R[0];c!=0;c=R[c])
        if(vis[c])
        {
            res++;
            vis[c]=false;
            for(int i=D[c];i!=c;i=D[i])
                for(int j=R[i];j!=i;j=R[j])
                    vis[Col[j]]=false;
        }
        return res;
    }
    void Dance(int d)//d为递归深度
    {
        if(d+h()>=ansd)return;
        if(R[0]==0)//找到解
        {
            if(d<ansd)ansd=d;
            return;
        }
        //找S最小的C列
        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])//用结点i所在的行覆盖第c列
        {
            Remove(i);
            for(int j=R[i];j!=i;j=R[j])Remove(j);//删除节结点i所在行覆盖第c列
            Dance(d+1);
            for(int j=L[i];j!=i;j=L[j])Resume(j);// 恢复
            Resume(i);
        }
    }
};
DLX g;
int id[20][20];
int main()
{
    int n,m,x,c,r;
    while(scanf("%d%d",&n,&m)>0)
    {
        int sz=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&x);
            id[i][j]=x?++sz:0;
        }
        g.init(n*m,sz);
        scanf("%d%d",&r,&c);
        for(int i=1,num=1;i<=n;i++)
        for(int j=1;j<=m;j++,num++)
        {
            for(int x=0;x+i<=n&&x<r;x++)
                for(int y=0;y+j<=m&&y<c;y++)
                if(id[i+x][y+j])
                g.Link(num,id[i+x][j+y]);
        }
        g.ansd=n*m;
        g.Dance(0);
        printf("%d\n",g.ansd);
    }
}

时间: 2025-01-13 06:21:13

FZU 1686(重复覆盖)的相关文章

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建图重复覆盖

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

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

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

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

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

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

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

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

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

FZU 2165 v11(最小重复覆盖)

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

FZU 1686 神龙的难题 (DLX)

神龙的难题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice FZU 1686 Appoint description:  System Crawler  (2015-04-16) Description 这是个剑与魔法的世界.英雄和魔物同在,动荡和安定并存.但总的来说,库尔特王国是个安宁的国家,人民安居乐业,魔物也比较少.但是.总有一些魔物不时会

HDU 3335 Divisibility(DLX可重复覆盖)

Problem Description As we know,the fzu AekdyCoin is famous of math,especially in the field of number theory.So,many people call him "the descendant of Chen Jingrun",which brings him a good reputation. AekdyCoin also plays an important role in th

FZU_1686_神龙的难题(DancingLinksX重复覆盖)

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