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;
}
View Code

 

 

 

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;
}
View Code

 

zoj 3209 Treasure Map

题意:在 n*m的平面中有p (1 <= nm <= 30, 1 <= p <= 500)个小矩形,每个小矩形有其所在位置,问从中选出最少数目个使得覆盖整个平面并且不重合。

直接暴力碾压过去。。对每个小矩形为行,为其能覆盖的点(格子?)为列,跑DLX

注意每个点应该[x0,x1), [y0, y1) 即统一只覆盖某边界

 

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define N 505
#define M 1005
#define T 500005
#define INF 0x3f3f3f3f
struct DLX{
    int r[T], u[T], l[T], d[T];
    int cnt[M], col[T], head[N];
    int n, id;
    
    void init(int nt){
        this->n = nt;
        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(head, -1, sizeof(head));
    }

    void add(int rr, int cc){
        d[id] = cc;    u[id] = u[cc];
        d[u[cc]] = id;    u[cc] = id;

        if(head[rr] < 0){
            head[rr] = l[id] = r[id] = id;
        }
        else {
            l[id] = head[rr];    r[id] = r[head[rr]];
            l[r[head[rr]]] = id;    r[head[rr]] = id;
            head[rr] = id;
        }
        cnt[cc] ++;    col[id] = cc;
        id ++;
    }

    void remove(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];
            }
        }
        return ;
    }

    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;
    }

    int dfs(){
        if(r[0] == 0) {
        return 0;}
        int idx, temp = INF, ans = INF, i, j;

        for(i = r[0]; i != 0; i = r[i]){
            if(cnt[i] < temp){
                temp = cnt[i];
                idx = i;
            }
        }    
    //    printf("%d\n", idx);
        if(temp == 0) return INF;
        remove(idx);
        for(i = d[idx]; i != idx; i = d[i]){
            for(j = r[i]; j != i; j = r[j]){
                remove(col[j]);
            }

            ans = min(ans, dfs());
            for(j = l[i]; j != i; j = l[j]){
                resume(col[j]);
            }
        }
        resume(idx);
        return ans + 1;
    }

}dlx;



int main(void){
    int TC, n, p, m, i, j, k, ans;
    int x1, y1, x2, y2;
    scanf("%d", &TC);
    while(TC--){
        scanf("%d%d%d", &n, &m, &p);
        dlx.init(m*n);

        for(i = 1; i <= p; i++){
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            for(j = x1; j < x2; j++){
                for(k = y1; k < y2; k++){
                    dlx.add(i, 1 + j * m + k);
                }
            }
        }
        ans = dlx.dfs();
        if(ans >= INF) ans = -1;
        printf("%d\n", ans);

    }
    return 0;
}
View Code

 

 

HDU 3498 whosyourdaddy

题意:攻击一个点可以同时攻击其相邻点,(不超过4个) ,问最少攻击多少个点能攻击完所有点。

做法。。裸。。。注意剪枝

if(ct + H() > ANS) return; 是过不了的。。
if(ct + H() >= ANS) return;才行

 

 

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

#define N 60
#define T 4000
#define INF 0x3f3f3f3f

bool f[N][N];
int ANS;
struct DLX{
    int l[T], r[T], u[T], d[T];
    int cnt[N], head[N], row[T], col[T];
    bool vis[N];
    int id, n;
    void init(int nt){
        this->n = nt;
        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(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, j;
        for(i = u[x]; i != x; i = u[i]){
            l[r[i]] = l[i];    r[l[i]] = r[i];
        }
    }

    int H(){
        memset(vis, false, sizeof(vis));
        int ans = 0, i, j, k;
        for(i = r[0]; i != 0; i = r[i]){
            if(vis[i]) continue;
            ans ++;    vis[i] = true;
            for(j = d[i]; j != i; j = d[j]){
                for(k = r[j]; k != j; k = r[k]){
                    vis[col[k]] = true;
                }
            }
        }
        return ans;
    }
    void resume(int x){
        int i;
        for(i = d[x]; i != x; i = d[i]){
            l[r[i]] = i;    r[l[i]] = i;
        }
    }

    void dfs(int ct){
        if(ct + H() >= ANS) return;
        if(r[0] == 0) {
            ANS = min(ANS, ct);
            return;
        //    return true;
        }
        int idx, temp = INF, ans = INF, i, j;
        for(i = r[0] ;i != 0; i = r[i]){
            if(cnt[i] < temp){
                temp = cnt[i];
                idx = i;
            }

        }
    //    printf("%d\n", idx);
        for(i = d[idx]; i != idx; i =d[i]){
            remove(i);
            for(j = r[i]; j != i; j = r[j]){
                remove(j);
            }
            //if(dfs(ct+1))     ans = true;
            dfs(ct + 1);
            for(j = l[i]; j != i; j = l[j]){
                resume(j);
            }
            resume(i);
        }

    //    return false;
    }
}dlx;

int main(){
    int n, m, x, y;
    int i, j;
    while(scanf("%d%d", &n, &m) != EOF){
        dlx.init(n);
        memset(f, false, sizeof(f));

        while(m--){
            scanf("%d%d", &x, &y);
            f[x][y] = f[y][x] = true;
        }

        for(i = 1; i <= n; i++){
            f[i][i] = true;
            for(j = 1; j <= n; j++){
                if(f[i][j]) dlx.add(i, j);
            }
        }
        ANS = n;
        dlx.dfs(0);
        printf("%d\n", ANS);
    }
    return 0;
}
View Code

 

 

HDU 3529 Bomberman - Just Search!

题意:炸弹人游戏,在空地放炸弹可以炸到以它为十字中心的最近的砖块,如果路上有石头冲击波就被拦住了。现在设所有炸弹同时爆炸,问最少放多少个炸弹。

做法:继续裸题。。就是为了练敲板正确度

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

#define N 240
#define M 44
#define T 11560
#define INF 0x3f3f3f3f

int ans, mapa[22][22], mapb[22][22];
char map[22][22];
bool f[N][M];
/*
struct DLX{
    int l[T], r[T], u[T], d[T];
    int head[N], row[T], col[T], cnt[M];
    bool vis[M];
    int id, n;






}dlx;
*/

struct DLX{
    int l[T], r[T], u[T], d[T];
    int cnt[N], head[N], row[T], col[T];
    bool vis[N];
    int id, n;
    void init(int nt){
        this->n = nt;
        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(head, -1, sizeof(head));
    }    void add(int rr, int cc){
        d[id] = cc;    u[id] = u[cc];
        d[u[cc]] = id;    u[cc] = id;

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


    int H(){
        memset(vis, false, sizeof(vis));
        int i, j, k, ans = 0;
        for(i = r[0]; i != 0; i =r[i]){
            if(vis[i]) continue;
            ans ++;    
            vis[i] = true;

            for(j = d[i]; j != i; j = d[j]){
                for(k = r[j] ;k != j; k = r[k]){
                    vis[col[k]] = true;
                }
            }
        }
        return ans;
    }

    void resume(int x){
        int i;
        for(i =d[x]; i != x; i =d[i]){
            l[r[i]] = i;    r[l[i]] = i;
        }
    }



    void dfs(int ct){
        if(ct + H() >= ans) return;

        if(r[0] == 0){
            ans = min(ans, ct);
            return;
        }
        int i, idx, temp = INF, j;
        for(i = r[0]; i != 0; i = r[i]){
            if(cnt[i] < temp){
                temp = cnt[i];
                idx = i;
            }
        }

        for(i = d[idx]; i != idx; i =d[i]){
            del(i);
            for(j = r[i]; j != i; j =r[j]){
                del(j);
            }
            dfs(ct + 1);
            for(j  = l[i]; j != i; j = l[j]){
                resume(j);
            }
            resume(i);
        }

    }


}dlx;
int gox[4] = {0, 0, -1, 1}, goy[4] = {-1, 1, 0, 0};
    
int main(){
    int n, m, i, j, ida, idb;
    int k, xx, yy;
    while(scanf("%d%d", &n, &m) != EOF){
        ida = idb = 0;
        for(i = 1; i <= n; i++){
            scanf("%s", map[i]+1);
            for(j = 1; j <= m; j++){
                if(map[i][j] == '.') mapa[i][j] = ++ida;
                else if(map[i][j] == '#') mapb[i][j] = ++idb;
            }
        }
        dlx.init(idb);
        memset(f, 0, sizeof(f));
        for(i = 2; i < n; i++){
            for(j = 2; j < m; j++){
                if(map[i][j] == '.'){ 
                    //void build(int x, int y){
                    for(k = 0; k < 4; k++){
                        xx = i + gox[k];    yy = j + goy[k];
                        while(true){
                            if(map[xx][yy] == '*') break;
                            if(map[xx][yy] == '#'){
                                f[mapa[i][j]][mapb[xx][yy]] = true;
                                break;
                            }
                            xx += gox[k];    yy += goy[k];

                        }
                    }
                }
            }
        }
        for(i = 1; i <= ida; i++){
            for(j = 1; j <= idb; j++){
                if(f[i][j]) dlx.add(i, j);
            }
        }
        //printf("!!\n");
        ans = ida;
        dlx.dfs(0);
        printf("%d\n", ans);
    }
    return 0;
}
View Code

 

HDU 2295 Radar

题意:对于一个发射站可以覆盖以他为圆心的半径是 r的园内的城市,每个发射站半径相同,问使得从备选的M个发射站中选出K个覆盖所有N个城市的最小半径是多少。

二分半径,重复覆盖,搜索时当ct+H() > K 就是不行

1. 1 ≤ T ≤ 20 
2. 1 ≤ N, M ≤ 50 
3. 1 ≤ K ≤ M 
4. 0 ≤ X, Y ≤ 1000 

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

#define N 55
#define T 3003
#define INF 0x3f3f3f3f
int dis[N][N];
int K;
struct DLX{
    int l[T], r[T], u[T], d[T];

    int cnt[N], col[T], row[T], head[N];
    bool vis[N];
    int n, id;
    void init(int nt){
        int i;
        this->n = nt;

        for(i = 0; i <= n; i++){
            u[i] = d[i] = i;
            l[i] = i -1;    r[i] = i + 1;
        }
        l[0] = n;    r[n] = 0;
        id = n + 1;
        memset(cnt, 0, sizeof(cnt));
        memset(head, -1, sizeof(head));
    }

    void add(int x, int y){
        u[id] = u[y];    d[id] = y;
        d[u[y]] = id;    u[y] = id;
        
        
        if(head[x] == -1){
            head[x] = l[id] = r[id] = id;
        }else{
            l[id] = head[x];    r[id] = r[head[x]];
            l[r[head[x]]] = id;    r[head[x]] = id;    
        }
        col[id] = y;    row[id] = x;
        cnt[y] ++;    id++;
    }


    void del(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]] = r[l[i]] = i;
        }
    }

    int H(){
        memset(vis, false, sizeof(vis));

        int i, j,k, ans = 0;

        for(i = r[0]; i != 0; i = r[i]){
            if(vis[i]) continue;
            ans ++;    vis[i] = true;
            for(j = d[i]; j != i; j = d[j]){
                for(k = r[j]; k != j; k = r[k]){
                    vis[col[k]] = true;
                }
            }
        }

        return ans;
    }

    bool dfs(int ct){
        if(ct + H() > K) return false;

        if(r[0] == 0) return true;

        int i, j, idx, temp = INF;

        for(i = r[0]; i != 0; i = r[i]){
            if(cnt[i] < temp){
                temp = cnt[i];    idx = i;
            }
        }
        for(i = d[idx]; i != idx; i = d[i]){
            del(i);
            for(j = r[i]; j != i; j =r[j]){
                del(j);
            }
            if(dfs(ct + 1)) return true;
            for(j = l[i]; j != i; j = l[j]){
                resume(j);
            }
            resume(i);
        }
        return false;
    }


}dlx;
int n, m;
struct point{
    int x, y;
}p[N], q[N];


void cal(void ){
    int i, j;
    for(i = 1; i <= m; i++)
        for(j = 1; j <= n; j++)
            dis[i][j] = (q[i].x-p[j].x)* (q[i].x-p[j].x)
                + (q[i].y-p[j].y)* (q[i].y-p[j].y);
}


void build(int mid){
    dlx.init(n);

    int i, j;
    for(i = 1; i <= m; i++){
        for(j = 1; j <= n; j++){
            if(mid >= dis[i][j]){

                dlx.add(i, j);
            }
        }
    }

}

int main(){
    int TC;
    scanf("%d", &TC);
    int i, j;
    while(TC--){
        scanf("%d%d%d", &n, &m, &K);
        for(i = 1;  i <= n; i++){
            scanf("%d%d", &p[i].x, &p[i].y);
        }
        for(j = 1; j <= m; j++){
            scanf("%d%d", &q[j].x, &q[j].y);
        }
        cal();

        
        int low = 0, high =INF, mid, ans;

        while(low <= high){
            mid = (low + high) >> 1;

            build(mid);
            if(dlx.dfs(0)){
                ans = mid;
                high = mid - 1;
            }
            else low = mid + 1;
        }

        printf("%.6f\n", (double)sqrt((double)ans));
    }
    return 0;
}
View Code

 

HDU 3656 Fire station

题意类似,从N个城市中选M个建消防站,使得所有城市到离他最近的消防站的距离最小。

不过直接对一大波范围二分会T,注意到半径一定是离消防站某个城市的距离,处理出城市两两之间所有距离,二分+重复覆盖

s (1 ≤ M ≤N ≤ 50),  (0 ≤ Xi, Yi ≤ 10000)

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

#define N 55
#define T 4003
#define INF 0x3f3f3f3f
int n, m;
int dis[N][N], num[T];
int maxn;
struct DLX{
    int l[T], r[T], u[T], d[T];
    int cnt[N], col[T], head[N];
    bool vis[N];

    int id, n;

    void init(int nt){
        this->n = nt;
        int i;
        for(i = 0; i <= n; i++){
            u[i] = d[i]  = i;
            l[i] = i-1;    r[i] = i + 1;

        }
        l[0] = n;    r[n]  = 0;
        memset(cnt, 0, sizeof(cnt));
        memset(head, -1, sizeof(head));
        id = n + 1;
    }

    void add(int x, int y){
        d[id] = y;    u[id] = u[y];
        d[u[y]] = id;    u[y] = id;

        if(head[x] == -1){
            head[x] = l[id] = r[id] = id;
        }
        else{
            l[id ] = head[x];    r[id] = r[head[x]];
            l[r[head[x]]] = id;    r[head[x]] = id;
            head[x] = id;
        }
        col[id] = y;    cnt[y] ++;
        id ++;
    }

    void del(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]] = r[l[i]] = i;
        }
    }

    int H(){
        int i, j, k, ans = 0;
        memset(vis, false, sizeof(vis));
        for(i = r[0]; i != 0; i = r[i]){
            if(vis[i]) continue;
            ans ++;    vis[i] = true;
            for(j = d[i]; j != i; j = d[j]){
                for(k = r[j] ; k != j; k = r[k]){
                    vis[col[k]] = true;
                }
            }
        }
        return ans;
    }
    bool dfs(int ct){
        if(ct + H() > m) return false;
        if(r[0 ] == 0) return true;
        
        int i, j, idx, temp = INF;
        for(i = r[0]; i != 0; i = r[i]){
            if(cnt[i] < temp){
                temp = cnt[i];
                idx = i;
            }
        }
        for(i = d[idx]; i != idx; i = d[i]){
            del(i);
            for(j = r[i]; j != i; j =r[j]){
                del(j);
            }if(dfs(ct + 1)) return true;
            for(j = l[i]; j != i; j = l[j]){
                resume(j);
            }
            resume(i);
        }
        return false;
    }


}dlx;
struct point{
    int x, y;
}p[N];

void cal(){
    int i, j;
    dis[0][0] = 0;
    for(i = 1; i <= n; i++){
        for(j = 1; j <= n; j++){
            dis[i][j] = (p[i].x-p[j].x)*(p[i].x-p[j].x)
                +(p[i].y-p[j].y)*(p[i].y-p[j].y);
        //    dis[0][0] = max(dis[0][0], dis[i][j]);
        //    printf("%d ", dis[i][j]);
            num[++maxn] = dis[i][j];
        }
        //printf("\n");
    }
}
void build(int mid){
    int i, j;
    dlx.init(n);

    for(i = 1; i <= n; i++){
        for(j = 1; j <= n; j++){
            if(dis[i][j] <= mid)     dlx.add(i, j);
        }
    }
}



int main(void){
    int TC, i;

    int low, mid, ans, high;

    scanf("%d", &TC);
    while(TC--){
        scanf("%d%d", &n, &m);
        for(i = 1; i <= n; i++){
            scanf("%d%d", &p[i].x, &p[i].y);
        }
        maxn = 0;    cal();

        sort(num + 1, num + 1 + maxn);
//        for(i = 1; i <= maxn; i++) printf("%d\n", num[i]);
    
        maxn = unique(num+1, num+1+maxn)-num;
    //    printf("%d\n", maxn);
        low = 1;    high = maxn-1;
        while(low <= high){
            mid = (low+high)>>1;
            build(num[mid]);
            if(dlx.dfs(0)){
                ans = num[mid];
                high = mid -1;
            }
            else low = mid + 1;
        }
        printf("%.6f\n", sqrt((double)ans));
    }
    return 0;
}
View Code

 

HDU 2518 

题意:http://acm.hdu.edu.cn/showproblem.php?pid=2518

就是用如图的图形,可以旋转,对称,排出n*m的矩形(n * m == 60)
问方案数
对12个图形和60个格子为列。对于每个图形,打表每个图形每种样子覆盖一个5个格子的方案为一行,对第i图形的方案第i列为1,覆盖的5个格子列为1.
跑DLX..
很慢。。。所以打个表。。。
//解释一个下面打表的程序,每个图形以第一行最左端为第一个位置,按行从上到下,列从左到右的顺序写出其他位置相对第一个位置的偏移。
//因为*/会把前面的注释取消掉。。强行变成了下面这个样子交上去。。。
/*
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define N 88
#define M 140
#define INF 0x3f3f3f3f
#define T 420000
int kind[12] = {4, 2, 1, 4, 8, 4, 8, 4, 8, 4, 8, 8};
int row;
int gox[12][8][4] = {
    {   /******
             0          0      000         000
             0          0        0         0
             000      000        0         0
        ********
        {1,2,2,2},  {1,2,2,2}, {0,0,1,2}, {0,0,1,2}
    },
    {   /******
             00000    0
                      0
                      0
                      0
                      0           ********
           {0,0,0,0},{1,2,3,4}
    },
    {   /******
            0
           000
            0         ********
         {1, 1, 1, 2}
    },
    {   /******
        0 0       000       00      00
        000       0 0       0        0
                            00      00
        ********
       {0,1,1,1},{0,0,1,1},{0,1,2,2},{0,1,2,2}
    },
    {   /******
        0           00      0000        0
        0000        0          0        0
                    0                   0
                    0                  00
       ********
       {1,1,1,1}, {0,1,2,3},{0,0,0,1},{1,2,3,3},

       /******
                   00                   0
        0000        0          0        0
        0           0       0000        0
                    0                   00
       ********
       {0,0,0,1},{0,1,2,3},{1,1,1,1},{1,2,3,3}
    },
    {
    /******
        0           00      00         0
        00         00        00       00
         00        0          0      00

       *******
        {1,1,2,2},{0,1,1,2},{0,1,1,2},{1,1,2,2}
    },
    {/******
      0            0        0000        0          0        0       0000            0
     0000          00         0         0        0000       0        0             00
                   0                   00                   00                      0
                   0                    0                   0                       0
    ********
     {1,1,1,1},{1,1,2,3}, {0,0,0,1}, {1,2,2,3}, {1,1,1,1},{1,2,2,3},{0,0,0,1},{1,1,2,3}
    },
    {
    /******
        0       00          0          00
      000        0          000        0
      0          00           0       00
    ********
      {1,1,1,2},{0,1,2,2}, {1,1,1,2},{0,1,2,2}
    },
    {/******
          0      0          00       0           0        0      00      0
          00     000       00       000         00      000       00    000
         00       0         0         0          00      0        0     0
    ******** /
       {1,1,2,2},{1,1,1,2},{0,1,1,2},{1,1,1,2},{1,1,2,2},{1,1,1,2},{0,1,1,2},{1,1,1,2}
    },
    {/******
        0           000         0           0
        0            0        000           000
       000           0          0           0
    ******** /
        {1,2,2,2}, {0,0,1,2}, {1,1,1,2}, {1,1,1,2}
    },
    {/******
            00      0       000         00          00          0       000       00
           000      00      00          00          000        00        00       00
                    00                   0                     00                 0
    ***** /
        {0,1,1,1},{1,1,2,2},{0,0,1,1},{0,1,1,2},{0,1,1,1}, {1,1,2,2},{0,0,1,1},{0,1,1,2}
    },
    {/******
        000        0         00         0        000           0       00        0
       00          00      000          0          00         00        000      0
                    0                   00                    0                 00
                    0                    0                    0                 0
    ******* /
       {0,0,1,1},{1,1,2,3}, {0,1,1,1},{1,2,2,3},{0,0,1,1},{1,1,2,3}, {0,1,1,1},{1,2,2,3}
    }
};
int goy[12][8][4] = {
    {   /******
             0          0      000         000
             0          0        0         0
             000      000        0         0
        ******** /
        {0,0,1,2},  {0,-2,-1,0}, {1,2,2,2}, {1,2,0,0}
    },
    {   /******
             00000    0
                      0
                      0
                      0
                      0           ******** /
           {1,2,3,4},{0,0,0,0}
    },
    {   /******
            0
           000
            0         ******** / 
         {-1,0,1,0}
    },
    {   /******
        0 0       000       00      00
        000       0 0       0        0
                            00      00
        ******** /
        {2,0,1,2},{1,2,0,2},{1,0,0,1},{1,1,0,1}
    },
    {   /******
        0           00      0000        0
        0000        0          0        0
                    0                   0
                    0                  00
       ******** /
       {0,1,2,3},{1,0,0,0},{1,2,3,3}, {0,0,-1,0},
       /******
                   00                   0
        0000        0          0        0
        0           0       0000        0
                    0                   00
       ******** /
       {1,2,3,0},{1,1,1,1},{-3,-2,-1,0},{0,0,0,1}
    },
    {
    /******
        0           00      00         0
        00         00        00       00
         00        0          0      00

       ******** /
        {0,1,1,2},{1,-1,0,-1},{1,1,2,2},{-1,0,-2,-1}
    },
    {/******
      0            0        0000        0          0        0       0000            0
     0000          00         0         0        0000       0        0             00
                   0                   00                   00                      0
                   0                    0                   0                       0
    ******** /
     {-1,0,1,2},{0,1,0,0},{1,2,3,2},{0,-1,0,0},{-2,-1,0,1},{0,0,1,0},{1,2,3,1},{-1,0,0,0}
    },
    {
    /******
        0       00          0          00
      000        0          000        0
      0          00           0       00
    ******** /
      {-2,-1,0,-2},{1,1,1,2},{0,1,2,2},{1,0,-1,0}
    },
    {/******
          0      0          00       0           0            0          00      0
          00     000       00       000         00          000           00    000
         00       0         0         0          00          0            0     0
    ******** /
       {0,1,-1,0},{0,1,2,1},{1,-1,0,0},{-1,0,1,1},{-1,0,0,1},{-2,-1,0,-1},{1,1,2,1},{-1,0,1,-1}
    },
    {/******
        0           000         0           0
        0            0        000           000
       000           0          0           0
    ******** /
        {0,-1,0,1},{1,2,1,1},{-2,-1,0,0},{0,1,2,0}
    },
    {/******
            00      0       000         00          00          0       000       00
           000      00      00          00          000        00        00       00
                    00                   0                     00                 0
    ***** /
        {1,-1,0,1},{0,1,0,1},{1,2,0,1},{1,0,1,1},{1,0,1,2},{-1,0,-1,0},{1,2,1,2},{1,0,1,0}
    },
    {/******
        000        0         00         0        000           0       00        0
       00          00      000          0          00         00        000      0
                    0                   00                    0                 00
                    0                    0                    0                 0
    ******** /
       {1,2,-1,0},{0,1,1,1},{1,-2,-1,0},{0,0,1,1},{1,2,2,3},{-1,0,-1,-1},{1,1,2,3},{0,-1,0,-1}
    }
};

int ans ;

struct DLX{
    int l[T], r[T], u[T], d[T];
    int col[T], cnt[N], head[T];

    int id, n;

    void init(int nt){
        this->n = nt;

        int i;
        for(i = 0; i <= n; i++){
            d[i] = u[i] = i;
            l[i] = i - 1; r[i] = i + 1;
        }
        l[0] = n; r[n] = 0;
        memset(cnt, 0, sizeof(cnt));
        memset(head, -1, sizeof(head));
        id=  n +1;
    }

    void add(int x, int y){
        u[id] = u[y]; d[id] = y;
        d[u[y]] = id; u[y] = id;

        if(head[x] == -1){
            head[x] = l[id] = r[id] = id;
        }
        else{
            r[id] = r[head[x]]; l[id] = head[x];
            l[r[id]] = id;  r[l[id]] = id;
            head[x] = id;
        }
        cnt[y] ++;  col[id] = y;
        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;
    }

    void dfs(){
        if(r[0] == 0)   {
            ans++;  return;
        }
        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;
        del(idx);
        for(i = d[idx]; i != idx; i = d[i]){
            for(j = r[i]; j != i; j = r[j]){
                del(col[j]);
            }
            dfs();
            for(j = l[i]; j != i; j = l[j]){
                resume(col[j]);
            }
        }
        resume(idx);
    }
}dlx;


int n, m;
void color(int domi, int ang, int x, int y){

    int i, j, xx, yy;
    for(i = 0; i < 4; i++){
        xx = x + gox[domi][ang][i];
        yy = y + goy[domi][ang][i];
        if(xx < 1 || xx > n || yy < 1 || yy > m) return;
    }
    dlx.add(++row, domi+1);
    dlx.add(row, m*(x-1)+y+12);
    for(i = 0; i < 4; i++){
        xx = x + gox[domi][ang][i];
        yy = y + goy[domi][ang][i];
         dlx.add(row, m*(xx-1)+yy+12);
    }
}


int dabiao[10];
int main(void){
//freopen("in", "r", stdin);
    int x,y,j, i;
    char map[20][20];
    /*
    while(scanf("%d", &n)){
        for(i = 0; i < kind[n]; i++){
            memset(map, 1, sizeof(map));
            map[1][10] = '*';
            for(j = 0; j < 4; j++){
                x = 1 + gox[n][i][j];
                y = 10 + goy[n][i][j];
                map[x][y] = '*';
            }
            for(j = 1; j <= 5; j++){
                for(int k = 5; k <= 15; k++){
                    printf("%c",map[j][k]);
                }
                printf("\n");
            }
            printf("\n");
        }
    }* /
    for(n = 1; n <=6; n ++){

   // while(scanf("%d", &n) != EOF){
        m = 60/n;
        ans = 0;    row = 0;
        dlx.init(72);
        for(i = 0; i < 12; i++){
            for(j = 0; j < kind[i]; j++){
                for(x=1; x <= n; x++){
                    for(y = 1; y <= m; y++){
                            color(i,j,x,y);
                    }
                }
            }
        }



        dlx.dfs();
        dabiao[i] = ans;
        printf("%d %d\n",n, ans / 4);
    }

    return 0;

}
*/

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

int ans[10] = {0, 0, 0, 2, 368, 1010, 2339};
int main(){
    int n, m;
    while(cin>>n>>m){
        if( n > m) swap(n, m);
        cout<<ans[n]<<endl;
    }
    return 0;
}
View Code

 

HDU 3156 Repair Depots

题意:给出n 个点 (1 <= n <= 16),浮点坐标。在平面上找出c个点,以他们为圆心半径为r的c个圆可以覆盖n个点,求半径r的最小值

做法。二分半径。

两两枚举两个点,并获得建立圆心的信息。对于点X(x, y), X'(xx, yy)

如果其距离== r 则在其中间建圆心。

<r 则可以建出两个圆心(使X, Y恰好在圆上)

注意要给每个点的位置也建一个圆心。

输出%f才过。。。多输几位好像不对? 不知道是我写错了还是题目看错了。。。不贴代码了免得误导orz

 

转载于:https://www.cnblogs.com/bbbbbq/p/4082627.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值