DancingLinks刷题集

HDU 3663 Power Stations 精确覆盖

题意:每个城市i有xi->yi天可以成为发射站,发射站覆盖范围为与该站有一条边链接的城市。

同时,每个每天城市必须且只能被一个发射站覆盖

天数D<=5。 每个城市的发射站关闭后就不再开启。即只能选择一段区间。

问若能做到,则输出每个城市开启时间与关闭时间

否则输出No solution

做法:

1.天数城市可独立看待,故每个城市每天看做一列。

2.在此区间内取一段子区间,注意到D很小,可枚举起点时刻终点时刻,每个城市每个方案作为一行。

3.对每个方案可覆盖到的城市及各天,则对该行该列设1

4.为解决每个城市只能取一段区间,则对每个城市设置一个新的列,该城市所有方案在该列设1,使不重复选择。

5.注意设置每个城市发射站未开启的方案行。因为不开是可行的。6。

注意多输出一行空行

//2014.11.7

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define N 1004
#define M 850
#define T 820000
#define INF 0x3f3f3f3f
vector<int>vec[66];
int dir[10];
bool g[66][66];
vector<int>v;
struct Day{
    int x,y;
    Day(){};
    Day(int xx, int yy): x(xx), y(yy){};
}p[66], ans[66], rec[N];
int yingying, f[N];
void dabiao(){
    int i;
    dir[0] = 0;
    for(i = 1; i <= 5; i++) dir[i] = i + dir[i-1];
}
struct DLX{
    int L[T], R[T], U[T], D[T];
    int head[N];
    int cnt[M], col[T], row[T], id, n, m;

    void init(int nn, int mm){
        this->n = nn;
        this->m = mm;

        int i;
        for(i = 0; i <= m; i++){
            D[i] = U[i] = i;
            L[i] = i-1;    R[i] = i + 1;
        }
        id = m + 1;
        R[m] = 0;    L[0] = m;
        memset(cnt, 0, sizeof(cnt));
        memset(head, -1, sizeof(head));

    }
    void add(int r, int c){
        D[id] =  c;    U[id] = U[c];
        D[U[c]] = id;    U[c]  = id;

        if(head[r] < 0 ){
            head[r] = L[id] = R[id] = id;
        }
        else {
            L[id] = head[r];    R[id] = R[head[r]];
            L[R[head[r]]] =id;    R[head[r]] = id;
            head[r] = id;
        }
        cnt[c] ++;    col[id] = c;    row[id] =r;
        id ++;
    }
    void del(int x){
        int i, j;
        L[R[x]] = L[x];    R[L[x]] = R[x];
        for(i = D[x]; i != x; i = D[i]){
            for(j = R[i]; j != i; j = R[j]){
                cnt[col[j]] --;
                U[D[j]] = U[j];    D[U[j]] = D[j];
            }
        }
    }

    void resume(int x){
        int i, j;
        for(i = U[x]; i != x; i = U[i]){
            for(j = L[i]; j != i; j = L[j]){
                cnt[col[j]] ++;
                D[U[j]] = j;    U[D[j]] = j;
            }
        }
        L[R[x]] = x;    R[L[x]] = x;
    }

    bool dfs(){
        if(R[0] == 0) return true;
        int idx , temp, i, j;
        temp = INF;
        for(i = R[0]; i != 0; i = R[i]){
            if(cnt[i] < temp){
                temp = cnt[i];
                idx = i;
            }
        }
        if(temp == 0) return false;

        del(idx);
        for(i = D[idx]; i != idx; i = D[i]){
            Day tttt = ans[f[row[i]]];
            ans[f[row[i]]] = rec[row[i]];
            for(j = R[i]; j != i; j = R[j]){
                del(col[j]);
            }
            if(dfs()) return true;
            for(j = L[i]; j != i; j = L[j]){
                resume(col[j]);
            }
            ans[f[row[i]]] = tttt;
        }
        resume(idx);
        return false;
    }
}dlx;

bool gao(int n, int d){
    int sum = 0, i, j, k, t, tt;
    for(i = 1; i <= n; i++){
        sum += dir[p[i].y - p[i].x];
    }

    dlx.init(sum, n * d + n);
    sum = 0;
    for(i = 1; i <= n; i++){
        for(j = p[i].x; j <= p[i].y; j++){
            for(k = j; k <= p[i].y; k++){
                ++sum;
                for(tt = 0; tt < vec[i].size(); tt++){
                    for(t = j; t <= k; t++){
                        dlx.add(sum, (vec[i][tt]-1)*d+t);
                    }
                }
                dlx.add(sum, n * d +i);
                rec[sum] = Day(j, k);
                f[sum] = i;
            }
        }
    }
    for(i = 1; i <= n; i ++){
        dlx.add(++sum, n * d + i);
        f[sum] = n + 1;
    }

    return dlx.dfs();

}

int main(void){
    int n, m, d, i, j, x, y;
    dabiao();
    while(scanf("%d%d%d", &n, &m, &d) != EOF){
        fill(vec, vec+66, vector<int>() );
        memset(g, false, sizeof(g));
        while(m--){
            scanf("%d%d", &x, &y);
            if(g[x][y]) continue;
            g[x][y] = g[y][x] = true;
            vec[x].push_back(y);    vec[y].push_back(x);
        }
        for(i = 1; i <= n; i++){
            scanf("%d%d", &p[i].x, &p[i].y);
            vec[i].push_back(i);
            ans[i] = Day(0, 0);
        }
        yingying = n;
        if(gao(n, d)){
            for(i = 1; i <= n; i++){
                printf("%d %d\n", ans[i].x, ans[i].y);
            }
        }
        else printf("No solution\n");
    printf("\n");

    }
    return 0;
}

HDU 2828 Lamp

重复覆盖+判断冲突

题意:有N盏灯可以由M个开关控制,对于第i盏灯,当条件A|| B || C。。。满足则灯亮,条件X为j开关OFF或ON状态。

问开关处于何种状态时,灯是全开的。SPJ

做法:

建图的第一部分很简单,以N盏灯为列,每个开关的开/关状态各为一行,对处于此状态为亮的灯为1.

然后是开关的状态只能取一个的解决方法。对于每个开关状态on / off是否采用,设置vis数组,若dfs时对应的另一个状态已经采用,则此状态非法,不搜。

以上,可解决。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define N 1004
#define T 1000004
#define INF 0x3f3f3f3f

int f[N][N>>1], ans[504];
vector<int>v;
int M ;
struct DLX{
    int r[T], l[T], u[T], d[T];
    int cnt[N], col[T], row[N], head[N];
    bool vis[N];
    int n, id;
    void init(int n){
        this->n = n;
        int i;
        for(i = 0; i <= n; i++){
            d[i] = u[i] = i;
            l[i] = i - 1;    r[i] = i + 1;
        }
        id = n + 1;
        r[n] = 0;    l[0] = n;
        memset(cnt, 0, sizeof(cnt));
        memset(vis, false, sizeof(vis));
        memset(head, -1, sizeof(head));
    }
    void add(int R, int C){
        d[id] =  C;    u[id] = u[C];
        d[u[C]] = id;    u[C]  = id;

        if(head[R] < 0 ){
            head[R] = l[id] = r[id] = id;
        }
        else {
            l[id] = head[R];    r[id] = r[head[R]];
            l[r[head[R]]] =id;    r[head[R]] = id;
            head[R] = id;
        }
        cnt[C] ++;    col[id] = C;    row[id] =R;
        id ++;
    }
    void remove(int x){
        int i;
        for(i = u[x]; i != x; i = u[i]){
            l[r[i]] = l[i];
            r[l[i]] = r[i];
        }
    }

    void resume(int x){
        int i;
        for(i = d[x]; i != x; i = d[i]){
            l[r[i]] = i;    r[l[i]] = i;
        }
    }
    bool dfs(){
        if(r[0] == 0) return true;

        int i, c = r[0], j;
        for(i = r[0]; i != 0; i = r[i]){
            if(cnt[i] <cnt[c]) c = i;
        }
        for(i = d[c]; i != c; i = d[i]){
            if(vis[row[i]^1] ) continue;
            vis[row[i]] = true;
            remove(i);
            for(j = r[i]; j != i; j = r[j]){
                remove(j);
            }

            if(dfs()) return true;
            for(j = l[i]; j != i; j = l[j])                    resume(j);
                resume(j);
            resume(i);        vis[row[i]] = false;
        }
        return false;

    }

}dlx;

bool gao(int n, int m){
    dlx.init(n);
    m <<= 1;

    int i, j;
    for(i = 0; i < m; i++){
        for(j = 1; j <= n; j++){
            if(f[i][j]){
                dlx.add(i, j);
            }
        }
    }
    return dlx.dfs();
}

int main(){
    int n, m, i, k, x;
    char op[10];
    while(scanf("%d%d", &n, &m) != EOF){
        memset(f, 0, sizeof(f));
        M = n;
        for(i = 1; i <= n; i++){
            scanf("%d", &k);
            while(k--){
                scanf("%d%s", &x, op);
                x--;
                if(op[1] == ‘N‘){
                    f[x<<1][i] = 1;
                }
                else f[x<<1|1][i] = 1;
            }

        }

        if(gao(n, m)){
            for(i = 0; i < m; i++){
                printf("%s%c", dlx.vis[i<<1] ? "ON": "OFF", i == m - 1? ‘\n‘ : ‘ ‘);
            }
        }
        else printf("-1\n");
    }
    return 0;
}
时间: 2024-10-16 06:23:25

DancingLinks刷题集的相关文章

动态规划刷题集python代码

1 最长公共子序列长度 def lcs(x,y,m,n): c = [[0]*(n+1)]*(m+1) print(len(c),len(c[0])) for i in range(m): for j in range(n): if x[i]==y[j]: c[i+1][j+1]=c[i][j]+1 else: c[i+1][j+1]=max(c[i+1][j],c[i][j+1]) return c[m][n] x = [1,3,2,5,6] y = [6,3,2,4,5,7,6] m,n =

跟着chengyulala刷题之[kuangbin带你飞]之&#39;并查集&#39;专题/斜眼笑

[kuangbin带你飞] 专题1-23 https://vjudge.net/article/187 专题五 并查集 POJ 2236 Wireless Network  http://poj.org/problem?id=2236POJ 1611 The Suspects  http://poj.org/problem?id=1611HDU 1213 How Many Tables  http://acm.hdu.edu.cn/showproblem.php?pid=1213HDU 3038

并查集刷题整理

并查集刷题整理 并查集是一种数据结构,然而用于维护其的数组及函数又极少,用途极为广泛,被广泛地应用于极多的综合题目, 比较经典的应用就是最小生成树\(kruskal\)算法 T1:Watering Hole G 题意 \(n\)个牧场,需要挖井,在第\(i\)号农场挖需要\(W_i\)元,在\(i\)与\(j\)号之间通水需要\(P_{i,j}=P_{j,i}\)元,问最小花费. 思路: 显然这并不是最短路问题,是最小生成树问题,目的就是将所有农场通过花费最小的路径进行串通 对于"挖井"

7、8月刷题总结

准备开学了囧,7.8月刷题记录,以后好来复习,并且还要好好总结! 数据结构: splay: [BZOJ]1503: [NOI2004]郁闷的出纳员(Splay) [BZOJ]1269: [AHOI2006]文本编辑器editor(Splay) [BZOJ]1507: [NOI2003]Editor(Splay) treap: [BZOJ]1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心) [BZOJ]3224: Tyvj

[转]POJ的刷题指南(加了超链接的)

网上看到的转过来一下,顺便把题目都加了个超链接,方便刷起~ POJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期: 一.基本算法:       (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.       (4)递推.       (5)构造法.(po

[2015.6.28] OI刷题记录

FZSZOJ刷题记录: 1051 砝码称重: DP 多重背包 1058 liqeuer: 序列DP 1061 挖地雷:DP,注意需要倒过来做DP,同时记录路径. 1059 Number:DP 1054 数塔问题:同数字三角形,普通DP 1390 等式问题:爆搜,枚举每个+号或-号的位置 1006 中位数:维护大根堆+小根堆,每次插入调整 1005 Cube Stacking:并查集维护当前在第几个和当前集合的高度,并查集变种. 1073 DNA分子的最佳比对:序列DP 1110 奖学金:傻逼题,

BZOJ 刷题记录 PART 5

拖了好久才写的. [BZOJ2821]接触分块大法.这道题略有点新颖.首先我们先分块,然后统计每块中每个数出现的个数. 下面是联立各个方块,预处理出第I个方块到第J个方块出现正偶数次数的个数. for (i=1;i<=s;i++) { for (j=i;j<=s;j++) { sum[i][j]=sum[i][j-1]; for (k=a[j].l;k<=a[j].r;k++) { temp[data[k]]++; if (!(temp[data[k]]&1)) sum[i][j

2019.8.7刷题统计

第一题:1118 这道题就是一个普通并查集,但是要记录以每个点为根的子树的结点个数. AC代码: 第二题:1120 对于这道题前面的讲解,我很奇怪,为什么要用C语言操作? 不过学学C语言总比不学好,既然已经讲过C语言的字符串操作了,就先用C语言打一遍. AC代码(C语言): 这是我在网站上交的第一份C语言程序,之前全部都是C++. 既然学的语言是C++,那么一定也要用C++打一遍. (C++的string比C语言中char[205]消耗内存多?) AC代码(C++): 和刚才的代码也差不多,不加

LeetCode开心刷题五十六天——128. Longest Consecutive Sequence

最近刷题进展尚可,但是形式变化了下,因为感觉眼睛会看瞎,所以好多写在纸上.本来想放到文件夹存储起来,但是太容易丢了,明天整理下,赶紧拍上来把 今晚是周末,这一周都在不停的学学学,我想下周怕是不能睡午觉了,中午回去床对我的诱惑太大了,我得想办法,一进门先把被褥收起来,再放个欢快的歌,中午少吃点,加油小可爱 之前欠下的烂帐,把太多简单题做完,导致剩下的都是难题,所以万万记住一点捷径都不要走 128看花花酱大神的解法,发现对hashtable的了解十分不足,甚至一些常见函数都不知道是干什么的 这道题涉