DLX模型问题

问题:sevenzero liked Warcraft very much, but he haven‘t practiced it for several years after being addicted to algorithms. Now, though he is playing with computer, he nearly losed and only his hero Pit Lord left. sevenzero is angry, he decided to cheat to turn defeat into victory. So he entered "whosyourdaddy", that let Pit Lord kill any hostile unit he damages immediately. As all Warcrafters know, Pit Lord masters a skill called Cleaving Attack and he can damage neighbour units of the unit he attacks. Pit Lord can choice a position to attack to avoid killing partial neighbour units sevenzero don‘t want to kill. Because sevenzero wants to win as soon as possible, he needs to know the minimum attack times to eliminate all the enemys.
 
Input
There are several cases. For each case, first line contains two integer N (2 ≤ N ≤ 55) and M (0 ≤ M ≤ N*N),and N is the number of hostile units. Hostile units are numbered from 1 to N. For the subsequent M lines, each line contains two integers A and B, that means A and B are neighbor. Each unit has no more than 4 neighbor units. The input is terminated by EOF.
 
Output
One line shows the minimum attack times for each case.

Sample Input
5 4
1 2
1 3
2 4
4 5
6 4
1 2
1 3
1 4
4 5

Sample Output
2
3

回答:题意大概是英雄可以放一个技能,使得一个点和与其相邻的点受到伤害,问最少攻击几个点能够让所有的点都受到至少一次伤害。

#include<cstdio>
#include<cstring>
#include<climits>
#define N 60
#define M 3600
using namespace std;
struct
{
    int col,row;
} node[M];
int l[M],r[M],d[M],u[M],h[M],res[N],cntcol[N];
int dcnt=-1,minn;
int n,m;
bool visit[N],mark[N][N];
int H()
{
    int count=0;
    bool hash[N];
    memset(hash,false,sizeof(hash));
    for(int i=r[0]; i!=0; i=r[i])
    {
        if(hash[i]) continue;
        //hash[i]=true;
        count++;
        for(int j=d[i]; j!=i; j=d[j])
            for(int k=r[j]; k!=j; k=r[k])
                hash[node[k].col]=true;
    }
    return count;
}
void addnode(int &x)
{
    ++x;
    r[x]=l[x]=u[x]=d[x]=x;
}
void insert_row(int rowx,int x)
{
    r[l[rowx]]=x;
    l[x]=l[rowx];
    r[x]=rowx;
    l[rowx]=x;
}
void insert_col(int colx,int x)
{
    d[u[colx]]=x;
    u[x]=u[colx];
    d[x]=colx;
    u[colx]=x;
}
void dlx_init(int cols)
{
    memset(h,-1,sizeof(h));
    memset(cntcol,0,sizeof(cntcol));
    dcnt=-1;
    addnode(dcnt);
    for(int i=1; i<=cols; ++i)
    {
        addnode(dcnt);
        insert_row(0,dcnt);
    }
}
void insert_node(int x,int y)
{
    //printf("insert %d %d\n",x,y);
    cntcol[y]++;
    addnode(dcnt);
    node[dcnt].row=x;
    node[dcnt].col=y;
    insert_col(y,dcnt);
    if(h[x]==-1) h[x]=dcnt;
    else insert_row(h[x],dcnt);
}
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]]=i;
        r[l[i]]=i;
    }
}
void DLX(int deep)
{
    if(deep+H()>=minn) return;
    if(r[0]==0)
    {
        if(minn>deep) minn=deep;
        return;
    }
    int min=INT_MAX,tempc;
    for(int i=r[0]; i!=0; i=r[i])
        if(cntcol[i]<min)
        {
            min=cntcol[i];
            tempc=i;
        }
    for(int i=d[tempc]; i!=tempc; i=d[i])
    {
        if(visit[node[i].row]) continue;
        res[deep]=node[i].row;
        remove(i);
        for(int j=r[i]; j!=i; j=r[j]) remove(j);
        DLX(deep+1);
        for(int j=l[i]; j!=i; j=l[j]) resume(j);
        resume(i);
    }
    return;
}
int main()
{
    int k;
    int a,b;
    for(; ~scanf("%d%d",&n,&m);)
    {
        memset(mark,false,sizeof(mark));
        dlx_init(n);//初始化
        for(; m--;)
        {
            scanf("%d%d",&a,&b);
            mark[a][b]=mark[b][a]=true;
        }
        for(int i=1; i<=n; ++i)
            for(int j=1; j<=n; ++j)
                if(mark[i][j]||i==j)
                    insert_node(i,j);
        minn=INT_MAX;
        DLX(0);
        printf("%d\n",minn);
    }
    return 0;
}

时间: 2024-12-28 01:24:44

DLX模型问题的相关文章

SPOJ 1771&amp;&amp;DLX精确覆盖,重复覆盖

DLX的题,做过这题才算是会吧. 这道题转化成了精确覆盖模型来做,一开始,只是单纯的要覆盖完行列和斜线,WA. 后来醒悟了,不能这样,只要覆盖全部行或列即可.虽然如此,但某些细节地方很关键不能考虑到. 特别要注意的是 for(int i=R[c];i;i=R[i]){ if(i>ne) break; if(S[i] < S[c]) c = i;} 找最小值只能是在ne之前,为什么呢?因为我们要完全覆盖行.可行吗?可行.稍微留意一下DLX的模板就知道,它其实在选中一列之后,是会枚举列上的行值,

FZU 1686 DLX建图重复覆盖

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

POJ 3074 Sudoku (DLX)

Sudoku Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3074 Appoint description:  System Crawler  (2015-04-18) Description In the game of Sudoku, you are given a large 9 × 9 grid divided into sm

zoj - 3209 - Treasure Map(精确覆盖DLX)

题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形可以恰好组成这个 n x m 的大矩形. 题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3372 -->>这是精确覆盖问题,而DLX正是解决精确覆盖问题的有利武器.. 模型转换:将原矩形变成一行,作为 DLX 中的列,表示要

1.RabbitMQ工作模型与基本原理

1.了解 MQ 的本质和 RabbitMQ 的特性: 2.掌握 RabbitMQ 的 Java API 编程和 Spring 集成 RabbitMQ 1. MQ 了解 1.1. 消息队列简介 1.1.1.MQ 的诞生历程 我们要去用 MQ,先来了解一下 MQ 是怎么诞生的,这样对于它解决了什么问题理解会更加深刻.世界上第一个 MQ 叫什么名字,是什么时候诞生的? 1983 年的时候,有个在 MIT 工作的印度小伙突发奇想,以前我们的软件相互通信,都是点对点的,而且要实现相同的协议,能不能有一种专

基于位置信息的聚类算法介绍及模型选择

百度百科 聚类:将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类.由聚类所生成的簇是一组数据对象的集合,这些对象与同一个簇中的对象彼此相似,与其他簇中的对象相异."物以类聚,人以群分",在自然科学和社会科学中,存在着大量的分类问题.聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法.聚类分析起源于分类学,但是聚类不等于分类.聚类与分类的不同在于,聚类所要求划分的类是未知的. 分类和聚类算法一直以来都是数据挖掘,机器学习领域的热门课题,因此产生了众多的

Laravel5.1 模型--ModelFactory

今天要说的是模型工厂,它是可以快速生成一些测试数据的东西,之前我们介绍过Seeder,当我们使用模型访问数据时 可以用模型工厂搭配Seeder使用. 1 编写一个ModelFactory ModelFactory的路径在 database/factories/ 下: // 这是系统自带的工厂 $factory->define(App\User::class, function ($faker) { return [ 'name' => $faker->name, 'email' =>

15.1-全栈Java笔记:Java事件模型是什么?事件控制的过程有哪几步??

应用前边两节上一章节的内容,大家可以完成一个简单的界面,但是没有任何的功能,界面完全是静态的,如果要实现具体功能的话,必须要学习事件模型. 事件模型简介及常见事件模型 对于采用了图形用户界面的程序来说,事件控制是非常重要的. 一个源(事件源)产生一个事件并把它(事件对象)送到一个或多个监听器那里,监听器只是简单地等待,直到它收到一个事件,一旦事件被接收,监听器将处理这些事件. 一个事件源必须注册监听器以便监听器可以接收关于一个特定事件的通知. 每种类型的事件都有其自己的注册方法,一般形式为: v

11.python并发入门(part13 了解事件驱动模型))

一.事件驱动模型的引入. 在引入事件驱动模型之前,首先来回顾一下传统的流水线式编程. 开始--->代码块A--->代码块B--->代码块C--->代码块D--->......--->结束 每一个代码块里是完成各种各样事情的代码,但编程者知道代码块A,B,C,D...的执行顺序,唯一能够改变这个流程的是数据.输入不同的数据,根据条件语句判断,流程或许就改为A--->C--->E...--->结束.每一次程序运行顺序或许都不同,但它的控制流程是由输入数据和