UVALive 2659+HUST 1017+ZOJ 3209+FZU 1686 (DLX

UVALive 2659

题目:16*16的数独.试了一发大白模板.

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

const int maxr = 5000;
const int maxn = 2000;
const int maxnode = 20000;

struct DLX {
    int n, sz;
    int S[maxn];

    int row[maxnode], col[maxnode];
    int L[maxnode], R[maxnode], U[maxnode], D[maxnode];

    int ansd, ans[maxr];

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

        for(int i = 0 ; i <= n; i++) {
            U[i] = i; D[i] = i; L[i] = i-1, R[i] = i+1;
        }
        R[n] = 0; L[0] = n;

        sz = n + 1;
        memset(S, 0, sizeof(S));
    }

    void addRow(int r, vector<int> &columns) {
        int first = sz;
        for(int i = 0; i < columns.size(); i++) {
            int c = columns[i];
            L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
            D[U[c]] = sz; U[c] = sz;
            row[sz] = r; col[sz] = c;
            S[c]++; sz++;
        }
        R[sz - 1] = first; L[first] = sz - 1;
    }

    #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) 

    void remove(int c) {
        L[R[c]] = L[c];
        R[L[c]] = R[c];
        FOR(i,D,c)
        FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
    }

    void restore(int c) {
        FOR(i,U,c)
        FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
        L[R[c]] = c;
        R[L[c]] = c;
    }

    bool dfs(int d) {
        if (R[0] == 0) {
            ansd = d;
            return true;
        }

        int c = R[0]; 
        FOR(i,R,0) if(S[i] < S[c]) c = i;

        remove(c);
        FOR(i,D,c) {
            ans[d] = row[i];
            FOR(j,R,i) remove(col[j]);
            if(dfs(d+1)) return true;
            FOR(j,L,i) restore(col[j]);
        }
        restore(c);

        return false;
    }

    bool solve(vector<int>& v) {
        v.clear();
        if(!dfs(0)) return false;
        for(int i = 0; i < ansd; i++) v.push_back(ans[i]);
            return true;
    }

}solver;

const int SLOT=0;
const int ROW=1;
const int COL=2;
const int SUB=3;

int encode(int a,int b,int c){
    return a*256+b*16+c+1;
}

char puzzal[20][20];

void decode(vector<int> &ans){
    for(int i=0;i<ans.size();i++){
        ans[i]--;
        int c=ans[i]%16;ans[i]/=16;
        int b=ans[i]%16;ans[i]/=16;
        int a=ans[i];
        puzzal[a][b]='A'+c;
    }
}
bool flag=0;
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    while(scanf("%s",puzzal[0])!=EOF){
        for(int i=1;i<16;i++){
            scanf("%s",puzzal[i]);
        }
        if(flag){
            puts("");
        }else{
            flag=1;
        }
        solver.init(1024);
        for(int r=0;r<16;r++){
            for(int c=0;c<16;c++){
                for(int v=0;v<16;v++){
                    if(puzzal[r][c]=='-'||puzzal[r][c]=='A'+v){
                        vector<int> columns;
                        columns.pb(encode(SLOT,r,c));
                        columns.pb(encode(ROW,r,v));
                        columns.pb(encode(COL,c,v));
                        columns.pb(encode(SUB,r/4*4+c/4,v));
                        solver.addRow(encode(r,c,v),columns);
                    }
                }
            }
        }
        vector<int> ans;
        solver.solve(ans);
        decode(ans);
        for(int i=0;i<16;i++){
            for(int j=0;j<16;j++){
                printf("%c",puzzal[i][j]);
            }
            puts("");
        }
    }
    return 0;
}
View Code

 HUST 1017

题目:裸精确覆盖,继续套模板.

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

const int maxr = 5000;
const int maxn = 2000;
const int maxnode = 1e6+3000;

struct DLX {
    int n, sz;
    int S[maxn];

    int row[maxnode], col[maxnode];
    int L[maxnode], R[maxnode], U[maxnode], D[maxnode];

    int ansd, ans[maxr];

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

        for(int i = 0 ; i <= n; i++) {
            U[i] = i; D[i] = i; L[i] = i-1, R[i] = i+1;
        }
        R[n] = 0; L[0] = n;

        sz = n + 1;
        memset(S, 0, sizeof(S));
    }

    void addRow(int r, vector<int> &columns) {
        int first = sz;
        for(int i = 0; i < columns.size(); i++) {
            int c = columns[i];
            L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
            D[U[c]] = sz; U[c] = sz;
            row[sz] = r; col[sz] = c;
            S[c]++; sz++;
        }
        R[sz - 1] = first; L[first] = sz - 1;
    }

    #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) 

    void remove(int c) {
        L[R[c]] = L[c];
        R[L[c]] = R[c];
        FOR(i,D,c)
        FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
    }

    void restore(int c) {
        FOR(i,U,c)
        FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
        L[R[c]] = c;
        R[L[c]] = c;
    }

    bool dfs(int d) {
        if (R[0] == 0) {
            ansd = d;
            return true;
        }

        int c = R[0]; 
        FOR(i,R,0) if(S[i] < S[c]) c = i;

        remove(c);
        FOR(i,D,c) {
            ans[d] = row[i];
            FOR(j,R,i) remove(col[j]);
            if(dfs(d+1)) return true;
            FOR(j,L,i) restore(col[j]);
        }
        restore(c);

        return false;
    }

    bool solve(vector<int>& v) {
        v.clear();
        if(!dfs(0)) return false;
        for(int i = 0; i < ansd; i++) v.push_back(ans[i]);
            return true;
    }

}solver;

int n,m;
vector<int> columns;
vector<int> ans;
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    while(cin>>n>>m){
        solver.init(m);
        for(int r=1;r<=n;r++){
            columns.clear();
            int x;
            scanf("%d",&x);
            for(int j=0;j<x;j++){
                int v;
                scanf("%d",&v);
                columns.pb(v);
            }
            solver.addRow(r,columns);
        }
        ans.clear();
        bool f=solver.solve(ans);
        if(!f){
            puts("NO");
            continue;
        }
        printf("%d",(int)ans.size());
        for(int i=0;i<ans.size();i++){
            printf(" %d",ans[i]);
        }
        puts("");
    }
    return 0;
}
View Code

 ZOJ 3209

题目:给出一张地图的若干个碎片,要求用最少的碎片恢复原地图.

思路:基本还是裸的dlx,搜的时候剪枝一下就好.

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF (1000000000)
#define FINF (1e3)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;

const int maxr = 5000;
const int maxn = 2000;
const int maxnode = 1e6+3000;

struct DLX {
    int n, sz;
    int S[maxn];

    int row[maxnode], col[maxnode];
    int L[maxnode], R[maxnode], U[maxnode], D[maxnode];

    int ansd, ans[maxr];

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

        for(int i = 0 ; i <= n; i++) {
            U[i] = i; D[i] = i; L[i] = i-1, R[i] = i+1;
        }
        R[n] = 0; L[0] = n;

        sz = n + 1;
        memset(S, 0, sizeof(S));
    }

    void addRow(int r, vector<int> &columns) {
        int first = sz;
        for(int i = 0; i < columns.size(); i++) {
            int c = columns[i];
            L[sz] = sz - 1; R[sz] = sz + 1; D[sz] = c; U[sz] = U[c];
            D[U[c]] = sz; U[c] = sz;
            row[sz] = r; col[sz] = c;
            S[c]++; sz++;
        }
        R[sz - 1] = first; L[first] = sz - 1;
    }

    #define FOR(i,A,s) for(int i = A[s]; i != s; i = A[i]) 

    void remove(int c) {
        L[R[c]] = L[c];
        R[L[c]] = R[c];
        FOR(i,D,c)
        FOR(j,R,i) { U[D[j]] = U[j]; D[U[j]] = D[j]; --S[col[j]]; }
    }

    void restore(int c) {
        FOR(i,U,c)
        FOR(j,L,i) { ++S[col[j]]; U[D[j]] = j; D[U[j]] = j; }
        L[R[c]] = c;
        R[L[c]] = c;
    }

    void dfs(int d) {
        if(ansd!=-1&&d>ansd) return;
        if (R[0] == 0) {
            if(ansd==-1)
                ansd = d;
            else
                ansd=min(ansd,d);
            return;
        }
        int c = R[0]; 
        FOR(i,R,0) if(S[i] < S[c]) c = i;

        remove(c);
        FOR(i,D,c) {
            ans[d] = row[i];
            FOR(j,R,i) remove(col[j]);
            dfs(d+1);
            FOR(j,L,i) restore(col[j]);
        }
        restore(c);
        return;
    }

    void solve(vector<int>& v) {
        v.clear();
        dfs(0);
        for(int i = 0; i < ansd; i++) v.push_back(ans[i]);
    }

}solver;

int T,n,m,p;
vector<int> columns;
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    cin>>T;
    while(T--){
        cin>>n>>m>>p;
        solver.init(n*m);
        for(int r=1;r<=p;r++){
            int x1,y1,x2,y2;
            columns.clear();
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            x1++,y1++;
            for(int i=x1;i<=x2;i++){
                for(int j=y1;j<=y2;j++){
                    columns.pb((i-1)*m+j);
                }
            }
            solver.addRow(r,columns);
        }
        solver.ansd=-1;
        solver.dfs(0);
        printf("%d\n",solver.ansd);
    }
    return 0;
}
View Code

 FZU 1686

题目;每次可以攻击一个矩形子矩阵,问最少攻击多少次达到目标.

思路:可重复覆盖的DLX和精确覆盖版的主要有这么几个区别

1)删除的时候,精确覆盖要求删去所有当前行已经覆盖的列,以及在已覆盖列上还有元素的所有行,而可重复覆盖只是删除已经覆盖的所有列.

2)由于可重复覆盖通常要求解最小步数,所以需要一个剪枝.

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-6)
#define IINF (1<<29)
#define LINF (1ll<<59)
//#define INF (1000000000)
#define FINF (1e3)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;


const int MaxM = 15*15+10;//width
const int MaxN = 15*15+10;//hight
const int maxnode = MaxN * MaxM;
const int INF = 0x3f3f3f3f;
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;
    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 v[MaxM];
    int f(){
        int ret = 0;
        for(int c = R[0]; c != 0;c = R[c])
            v[c] = true;
        for(int c = R[0]; c != 0;c = R[c]){
            if(v[c]){
                ret++;
                v[c] = false;
                for(int i = D[c];i != c;i = D[i]){
                    for(int j = R[i];j != i;j = R[j])
                        v[Col[j]] = false;
                }
            }
        }
        return ret;
    }
    void Dance(int d=0){
        if(d + f() >= ansd)return;
        if(R[0] == 0){
            if(d < ansd)ansd = d;
            return;
        }
        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]){
            remove(i);
            for(int j = R[i];j != i;j = R[j])remove(j);
                Dance(d+1);
            for(int j = L[i];j != i;j = L[j])resume(j);
                resume(i);
        }
    }
}dan;

int n,m;
int grid[20][20];
int id[20][20];
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    while(cin>>n>>m){
        int sz=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%d",&grid[i][j]);
                if(grid[i][j]) id[i][j]=sz++;
            }
        }
        dan.init(n*m,sz-1);
        int n1,m1;
        scanf("%d%d",&n1,&m1);
        sz=1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                for(int x=0;x<n1;x++){
                    for(int y=0;y<m1;y++){
                        if(i+x<n&&j+y<m&&grid[i+x][j+y]){
                            dan.Link(sz,id[i+x][j+y]);
                        }
                    }
                }
                sz++;
            }
        }
        dan.ansd=INF;
        dan.Dance();
        printf("%d\n",dan.ansd);
    }
    return 0;
}
View Code

 

posted @ 2015-09-24 22:46  PlusSeven  阅读(145)  评论(0编辑  收藏  举报