DLX专题

2 篇文章 0 订阅

[toc]
一下题目可以套白书模板

UVA 1309 Sudoku

把Sudoku上的点拆成如下信息
(r,c) 是否填了
(r,v),(c,v),(s,v) 第r行/c列/s块是否填了v

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

struct DLX {
    #define maxn (10000000+10)
    #define MAXNode (10000000+10)
    #define maxr (10000000)
    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;
        Rep(i,n+1) {
            U[i] = D[i] = i ; L[i]=i-1; R[i]=i+1;
        }
        R[n]=0; L[0]=n;
        sz=n+1;
        MEM(S)
    }

    void addRow(int r, vi columns) {
        int fir = sz;
        int cSz=columns.size();
        Rep(i,cSz) {
            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]=fir; L[fir] = 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 1;
        } 
        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 1;
            FOR(j,L,i) restore(col[j]);
        } 
        restore(c);
        return 0;
    }   
    bool solve(vi &v) {
        v.clear();
        if (!dfs(0)) return 0;
        Rep(i,ansd) v.pb(ans[i]);
        return 1;
    }   
};
DLX solver;
char puzzle[16][20];
bool init() {
    Rep(i,16) {
        if (scanf("%s",puzzle[i])!=1) return 0;
    }
    return 1;
}
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*16*16+b*16+c+1;
}
void decode(int code,int &a,int &b,int &c) {
    code--;
    c=code%16; code/=16;
    b=code%16; code/=16;
    a=code;
}
int main()
{
//  freopen("uva1309.in","r",stdin);
//  freopen(".out","w",stdout);
    bool fl=0;
    while(init()) {
        if (fl) puts("");   fl=1;
        solver.init(1024);
        Rep(r,16) Rep(c,16) Rep(v,16) { // put v in (r,c)
            if (puzzle[r][c]=='-'||puzzle[r][c]=='A'+v) {
                vi 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);
            } 
        }
        vi ans;
        solver.solve(ans);
        int sz=SI(ans);
        Rep(i,sz) {
            int a,b,c;
            decode(ans[i],a,b,c);
            puzzle[a][b]=c+'A';
        }
        Rep(r,16) puts(puzzle[r]);
    }


    return 0;
}

UVA 1469 Sudoku Extension

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

struct DLX {
    #define maxn (10000000+10)
    #define MAXNode (10000000+10)
    #define maxr (10000000)
    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;
        Rep(i,n+1) {
            U[i] = D[i] = i ; L[i]=i-1; R[i]=i+1;
        }
        R[n]=0; L[0]=n;
        sz=n+1;
        MEM(S)
    }

    void addRow(int r, vi columns) {
        int fir = sz;
        int cSz=columns.size();
        Rep(i,cSz) {
            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]=fir; L[fir] = 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;
    } 
    int t;
    bool dfs(int d) {
        if ( R[0] == 0) {
            ansd = d;
            ++t;
            return 1;
        } 
        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 0;
    }   
    bool solve() {
        t=0;
        if (!dfs(0)) return 0;
        return 1;
    }   
};
DLX solver;
const int N= 9;
const int SQN= 3;
char puzzle[N+10][N+10];
bool init() {
    Rep(i,N) {
        if (scanf("%s",puzzle[i])!=1) return 0;
    }
    return 1;
}
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*N*N+b*N+c+1;
}
int encode2(int a,int b) {
    return 729+a*N+b+1;
}
void decode(int code,int &a,int &b,int &c) {
    code--;
    c=code%N; code/=N;
    b=code%N; code/=N;
    a=code;
}
void decode2(int code,int &a,int &b) {
    code-=729+1;
    b=code%N; code/=N;
    a=code;
}
int main()
{
//  freopen("uva1461.in","r",stdin);
//  freopen(".out","w",stdout);
    int T=read();   
    while(init()&&T--) {
        solver.init(N*N*4);
        Rep(r,N) Rep(c,N) Rep(v,N) { // put v in (r,c)
            if (puzzle[r][c]=='0'||puzzle[r][c]=='1'+v||(puzzle[r][c]=='e'&&v%2==1) ||(puzzle[r][c]=='o'&&v%2==0) ) {
                vi columns;
                columns.pb(encode(SLOT,r,c));
                columns.pb(encode(ROW,r,v));
                columns.pb(encode(COL,c,v));
                columns.pb(encode(SUB,r/SQN*SQN+c/SQN,v));
                solver.addRow(encode(r,c,v),columns);
            } 
        }
        vi col[26][9];
        Rep(r,N) Rep(c,N) if (islower(puzzle[r][c])&&puzzle[r][c]!='e'&&puzzle[r][c]!='o') {
            Rep(v,N){
                int t=puzzle[r][c]-'a';
                col[t][v].pb(encode(SLOT,r,c));
                col[t][v].pb(encode(ROW,r,v));
                col[t][v].pb(encode(COL,c,v));
                col[t][v].pb(encode(SUB,r/SQN*SQN+c/SQN,v));
            }
        }
        Rep(t,26) Rep(v,N) if (!col[t][v].empty())
        {
            solver.addRow(encode2(t,v),col[t][v]);
        }

        solver.solve();

        cout<<solver.t<<endl;
    }


    return 0;
}

HDU 3498 whosyourdaddy

题目大意:一张无向图n<=55选至少几个点,使每条边至少有一个端点为所选点。

最小可支配集
DLX也可以用来解决重复覆盖问题,但是要加一个估价函数

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

namespace solver {
    #define maxn (50+10)
    #define MAXNode (10000+10)
    #define maxr (50+10)
    int n, sz;
    int S[maxn], H[maxr];
    int row[MAXNode],col[MAXNode];
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int ansd, ans[maxr]; 
    void init(int n) {
        Rep(i,n+1) {
            U[i] = D[i] = i ; L[i]=i-1; R[i]=i+1; S[i]=0;
        }
        R[n]=0; L[0]=n;
        sz=n+1;
        memset(H,-1,sizeof(H));
    }
    void link(int r,int c) {
        U[sz] = c;  D[sz] = D[c]; 
        U[D[c]] = sz; D[c] = sz;
        if (H[r]<0) H[r] = L[sz] = R[sz] = sz;
        else {
            L[sz] = H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]]  = sz ; R[H[r]] = sz;
        }
        S[c]++;     
        col[sz] = c;
        sz++;
    }
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])
    void remove(int c) {
        FOR(j,D,c) {
            L[R[j]] = L[j]; R[L[j]] = R[j]; 
        }
    } 
    void restore(int c) {
        FOR(j,U,c) {
            L[R[j]] =  R[L[j]] = j;
        } 
    } 
    //evaluation function
    bool vis[maxn];
    int A() {
        int ret=0;
        MEM(vis)
        FOR(i,R,0) {
            if (!vis[i]) {
                vis[i]=1;
                ++ret;
                FOR(j,D,i) 
                    FOR(k,R,j) 
                        vis[col[k]] = 1;
            }
        }
        return ret;
    } 
    void dfs(int d) {
        if ( R[0] == 0) {
            ansd = min(ansd,d);
            return;
        } 
        if (d+A()>=ansd) return ;
        int c = R[0];
        FOR(i,R,0) if (S[i] < S[c]) c = i;
        FOR(i,D,c) {
            remove(i);
            FOR(j,R,i) remove(j);//,--S[col[j]];
            dfs(d+1);
            FOR(j,L,i) restore(j);//,++S[col[j]];
            restore(i);
        } 
        return;
    }   
    bool solve() {
        ansd=INF;
        dfs(0);
        if (ansd==INF) return 0;
        return 1;
    }   
};
int a,b;
int n,m;
bool f[60][60];
int main()
{
//  freopen("hdu3498_data.in","r",stdin);
//  freopen("hdu3498.out","w",stdout);
    while(~scanf("%d%d",&n,&m)) {
        solver::init(n);
        For(i,n) For(j,n) f[i][j]=0;
        For(i,m) {
            scanf("%d%d",&a,&b);
            f[a][b]=f[b][a]=1;
        }
        For(i,n) f[i][i]=1;
        For(i,n) {
            For(j,n) if (f[i][j]) solver::link(i,j);
        }
        solver::solve();
        printf("%d\n",solver::ansd);
    }
    return 0;
}

HDU 2295 Radar

题目大意:一个国家有n个城市,有m个地方可以建造雷达,最多可以建K个雷达(K>=1 && K<=m),问雷达最短的探测半径,才能使n个城市都能探测到。1 ≤ N, M ≤ 50

重复覆盖+二分,记得搜到k时退出

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int n,m,K,ans;
struct DLX {
    #define MAXNode (10000+10)
    #define maxn (10000+10)
    #define maxm (60) 
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int sz,col[maxn],S[maxn],H[maxn];
    bool vis[maxm];
    void init(int m) {
        Rep(i,m+1) {
            L[i] = i-1;
            R[i] = i+1;
            U[i] = D[i] =i;
            S[i] = 0;
        } 
        memset(H,-1,sizeof(H));
        L[0]=m; R[m] = 0;
        sz=m+1;
    } 
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])   
    void remove(int c) {
        FOR(i,D,c) {
            L[R[i]] = L[i];
            R[L[i]] = R[i];
        }
    } 
    void resume(int c) {
        int i; 
        for(int i=U[c];i!=c;i=U[i]) {
            L[R[i]] = R[L[i]] = i;
        }
    } 
    void link(int r,int c) {
        U[sz] = c;
        D[sz] = D[c];
        U[D[c]] = sz;
        D[c] = sz;
        if (H[r]==-1) { H[r]=L[sz]=R[sz]=sz;    }
        else {
            L[sz] =H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]] = sz;
            R[H[r]] = sz;
        } 
        S[c]++ ; col[sz++]=c;
    } 
    int A() {
        MEM(vis)
        int res=0;
        FOR(i,R,0) {
            if (!vis[i]) {
                res++;
                vis[i] = 1;
                FOR(j,D,i) FOR(k,R,j) {
                    vis[col[k]]=1;
                } 
            } 
        } 
        return res;
    }
    void dfs(int d) {
        if (!R[0])  {
            ans=min(ans,d);
        } else if (d+A()<min(K+1,ans) ) {
            int c=R[0];
            FOR(i,R,0) {
                if (S[i]<S[c]) c=i;
            } 
            FOR(i,D,c) {
                remove(i);
                FOR(j,R,i) remove(j);
                dfs(d+1);
                FOR(j,L,i) resume(j);
                resume(i);
            } 
        } 
    } 
}solver; 
#define MAXN (60)
double x[MAXN],y[MAXN];
double a[MAXN],b[MAXN];

int main()
{
//  freopen("hdu2295.in","r",stdin);
//  freopen(".out","w",stdout);
    int T=read();
    while(T--) {
        n=read(); m=read(); K=read();
        For(i,n) scanf("%lf%lf",&x[i],&y[i]);
        For(i,m) scanf("%lf%lf",&a[i],&b[i]);
        double l=0,r=1416,eps=1e-8;
        while(r-l>eps) {
            double mid=(r+l)/2;
            solver.init(n);
            For(i,m) For(j,n) if (hypot(a[i]-x[j],b[i]-y[j])<=mid-eps ) {
                solver.link(i,j);
            }
            ans=INF;
            solver.dfs(0);
            if (ans<=K) r=mid-eps; else l=mid+eps;
        }
        printf("%.6lf\n",l);
    }
    return 0;
}

给一张N*M的矩阵,每个点要么是空的,要么有墙,要么又不可毁灭的障碍。问至少在几个空点设置炸弹,才能炸掉所有墙?一个炸弹能炸到4方向上最近的不为空点的点,所有炸弹同时爆炸,题目保证有解。
(4 <= N, M <= 15)

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int ans=0;
struct DLX {
    #define MAXNode (200000+10)
    #define maxn (400+10)
    #define maxm (400+10) 
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int sz,col[maxn],S[maxn],H[maxn];
    bool vis[maxm];
    void init(int m) {
        Rep(i,m+1) {
            L[i] = i-1;
            R[i] = i+1;
            U[i] = D[i] =i;
            S[i] = 0;
        } 
        memset(H,-1,sizeof(H));
        L[0]=m; R[m] = 0;
        sz=m+1;
    } 
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])   
    void remove(int c) {
        FOR(i,D,c) {
            L[R[i]] = L[i];
            R[L[i]] = R[i];
        }
    } 
    void resume(int c) {
        int i; 
        for(int i=U[c];i!=c;i=U[i]) {
            L[R[i]] = R[L[i]] = i;
        }
    } 
    void link(int r,int c) {
        U[sz] = c;
        D[sz] = D[c];
        U[D[c]] = sz;
        D[c] = sz;
        if (H[r]==-1) { H[r]=L[sz]=R[sz]=sz;    }
        else {
            L[sz] =H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]] = sz;
            R[H[r]] = sz;
        } 
        S[c]++ ; col[sz++]=c;
    } 
    int A() {
        MEM(vis)
        int res=0;
        FOR(i,R,0) {
            if (!vis[i]) {
                res++;
                vis[i] = 1;
                FOR(j,D,i) FOR(k,R,j) {
                    vis[col[k]]=1;
                } 
            } 
        } 
        return res;
    }
    void dfs(int d) {
        if (!R[0])  {
            ans=min(ans,d);
        } else if (d+A()<ans) {
            int c=R[0];
            FOR(i,R,0) {
                if (S[i]<S[c]) c=i;
            } 
            FOR(i,D,c) {
                remove(i);
                FOR(j,R,i) remove(j);
                dfs(d+1);
                FOR(j,L,i) resume(j);
                resume(i);
            } 
        } 
    } 
}solver;
int n,m;
#define MAXN (20)
char mat[MAXN][MAXN]; 
int h[MAXN][MAXN];
int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
int main()
{
//  freopen("hdu3529.in","r",stdin);
//  freopen(".out","w",stdout);

    while(cin>>n>>m) {
        Rep(i,n) cin>>mat[i];
        int N=0,M=0;
        Rep(i,n) Rep(j,m) {
            if (mat[i][j]=='.') {
                h[i][j]=++N;
            }
            if (mat[i][j]=='#') {
                h[i][j]=++M;
            }

        }
        solver.init(M);
        Rep(i,n) Rep(j,m) if (mat[i][j] == '.'){
            Rep(d,4) {
                int k=1;
                while(mat[i+k*dir[d][0]][j+k*dir[d][1]] == '.') ++k;
                if (mat[i+k*dir[d][0]][j+k*dir[d][1]]=='#') {
                    solver.link(h[i][j],h[i+k*dir[d][0]][j+k*dir[d][1]]);
                }
            }           
        }
        ans=INF;
        solver.dfs(0);
        cout<<ans<<endl;

    }

    return 0;
}

HDU 3957 Street Fighter

街霸游戏中,有n(2<=N<=25)种角色,每种角色有1~2种人物,从n种角色中选出哪些角色在那种人物上,可以击败其余的任何角色的任何人物。求选取的最少人物。

同时覆盖X精确覆盖 模板

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case %d: %d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int ans=0;
struct DLX {
    #define MAXNode (240000+10)
    #define maxn (600+10)
    #define maxm (600+10) 
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int sz,col[maxn],S[maxn],H[maxn];
    int n; 
    bool vis[maxm];
    void init(int m) {
        Rep(i,m+1) {
            L[i] = i-1;
            R[i] = i+1;
            U[i] = D[i] =i;
            S[i] = 0;
        } 
        memset(H,-1,sizeof(H));
        L[0]=m; R[m] = 0;
        sz=m+1;
    } 
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])   
    void remove(int c) {
        FOR(i,D,c) {
            L[R[i]] = L[i];
            R[L[i]] = R[i];
        }
    } 
    void resume(int c) {
        int i; 
        for(int i=U[c];i!=c;i=U[i]) {
            L[R[i]] = R[L[i]] = i;
        }
    } 

    //精确覆盖 
    void remove1(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 resume1(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 link(int r,int c) {
        U[sz] = c;
        D[sz] = D[c];
        U[D[c]] = sz;
        D[c] = sz;
        if (H[r]==-1) { H[r]=L[sz]=R[sz]=sz;    }
        else {
            L[sz] =H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]] = sz;
            R[H[r]] = sz;
        } 
        S[c]++ ; col[sz++]=c;
    } 
    int A() {
        MEM(vis)
        int res=0;
        FOR(i,R,0) {
            if(i>n) break;
            if (!vis[i]) {
                res++;
                vis[i] = 1;
                FOR(j,D,i) FOR(k,R,j) {
                    vis[col[k]]=1;
                } 
            } 
        } 
        return res;
    }
    void dfs(int d) {
        if (!R[0]||R[0]>n)  {
            ans=min(ans,d);
        } else if (d+A()<ans) {
            int c=R[0];
            FOR(i,R,0) {
                if(i>n) break;
                if (S[i]<S[c]) c=i;
            } 
            FOR(i,D,c) {
                remove(i);
                FOR(j,R,i) if (col[j]<=n) remove(j);
                FOR(j,R,i) if (col[j]>n) remove1(col[j]);

                dfs(d+1);
                FOR(j,L,i) if (col[j]>n) resume1(col[j]);
                FOR(j,L,i) if (col[j]<=n) resume(j);
                resume(i);
            } 
        } 
    } 
}solver;
int n,m;
#define MAXN (30)
int main()
{
//  freopen("hdu3957.in","r",stdin);
//  freopen(".out","w",stdout);
    int T=read();
    For(kcase,T) {
        cin>>n;
        solver.init(3*n);
        solver.n=2*n;
        int t=0;
        Rep(i,n) {
            cin>>m;
            Rep(j,m) {
                int u=2*i+j+1;
                int k=read();
                Rep(l,m) solver.link(u,2*i+l+1);
                while(k--) {
                    int a=read(),b=read();
                    if (a==i) continue;
                    int v=a*2+b+1;
                    solver.link(u,v);
                }
                solver.link(u,2*n+i+1);
            }
            if (m==1) solver.link(2*i+2,2*i+2),++t;
        }       
        ans=INF;
        solver.dfs(0);
        Pr(kcase,ans-t);        
    }

    return 0;
}

HDU 4735 Little Wish~ lyrical step~

题目大意:一棵树上有n<=50个结点,每个结点有一个男生或者一个妹纸,每条边有一个距离,问最少交换多少个人,使得妹纸在距离D内至少有一个男生.

注意这次求的是交换次数,所以要修改跳出条件(需要的男生超过男生总数或交换次数超过当前最优值),由于模板不小心抄错了数组大小对应关系,wa了

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %d\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int ans2=0;
bool b[60];
int boys;
struct DLX {
    #define MAXNode (10000+10)
    #define maxn (60)
    #define maxm (60) 
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int sz,col[MAXNode],S[maxn],H[maxn],row[MAXNode];
    bool vis[maxm];
    void init(int m) {
        Rep(i,m+1) {
            L[i] = i-1;
            R[i] = i+1;
            U[i] = D[i] =i;
            S[i] = 0;
        } 
        memset(H,-1,sizeof(H));
        L[0]=m; R[m] = 0;
        sz=m+1;
    } 
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])   
    void remove(int c) {
        FOR(i,D,c) {
            L[R[i]] = L[i];
            R[L[i]] = R[i];
        }
    } 
    void resume(int c) {
        int i; 
        for(int i=U[c];i!=c;i=U[i]) {
            L[R[i]] = R[L[i]] = i;
        }
    } 
    void link(int r,int c) {
        U[sz] = c;
        D[sz] = D[c];
        U[D[c]] = sz;
        D[c] = sz;
        if (H[r]==-1) { H[r]=L[sz]=R[sz]=sz;    }
        else {
            L[sz] =H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]] = sz;
            R[H[r]] = sz;
        } 
        S[c]++ ; row[sz]=r; col[sz++]=c;
    } 
    int A() {
        MEM(vis)
        int res=0;
        FOR(i,R,0) {
            if (!vis[i]) {
                res++;
                vis[i] = 1;
                FOR(j,D,i) FOR(k,R,j) {
                    vis[col[k]]=1;
                } 
            } 
        } 
        return res;
    }
    void dfs(int d,int l) {
        if (!R[0])  {
            ans2=min(ans2,d-l);
        } else if (d+A()<boys+1 && d-l < ans2 ) {
            int c=R[0];
            FOR(i,R,0) {
                if (S[i]<S[c]) c=i;
            } 
            FOR(i,D,c) {
                remove(i);
                FOR(j,R,i) remove(j);
                dfs(d+1,l+b[row[i]]);
                FOR(j,L,i) resume(j);
                resume(i);
            } 
        } 
    } 
}solver;
int n,D;
int f[60][60]; 
void floyd(int n) {
    For(k,n) For(i,n) For(j,n) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
int main()
{
//  freopen("hdu4735.in","r",stdin);
//  freopen(".out","w",stdout);
    int T=read();
    For(kcase,T) {
        n=read(),D=read();
        boys=0;
        For(i,n) b[i]=read(),boys+=b[i];
        MEMI(f)
        For(i,n-1) {
            int u=read(),v=read(),w=read();
            f[u][v]= f[v][u] = min(f[u][v],w);
        }
        For(i,n) f[i][i]=0;
        floyd(n);
        solver.init(n);
        For(i,n) For(j,n) if (f[i][j]<=D) solver.link(i,j);
        ans2=INF;
        solver.dfs(0,0);
        Pr(kcase,(ans2==INF)?(-1):(ans2));
    }
    return 0;
}

HDU 3663 Power Stations

有n个城市,还有m条边(双向),每个城市都有一个发电站,如果一个发电站工作,它能够给它所在的城市和直接相邻的城市提供电力。并且要求每个城市只能由一个发电站来提供电力(即不能够被两个或以上的发电站同时覆盖)。

区间拆成{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
{2, 2}, {2, 3}, {2, 4}, {2, 5},
{3, 3}, {3, 4}, {3, 5},
{4, 4}, {4, 5},
{5, 5}, {0, 0}};
列为第i天第j个city是否取,第i个发电站是否使用

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

struct DLX {
    #define maxn (60*16+10)
    #define MAXNode (370000+10)
    #define maxr (16*60+10)
    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;
        Rep(i,n+1) {
            U[i] = D[i] = i ; L[i]=i-1; R[i]=i+1;
        }
        R[n]=0; L[0]=n;
        sz=n+1;
        MEM(S)
    }

    void addRow(int r, vi columns) {
        int fir = sz;
        int cSz=columns.size();
        Rep(i,cSz) {
            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]=fir; L[fir] = 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;
    } 
    //evaluation function
    int H() {
        int ret=0;
        bool vis[maxn];
        FOR(i,R,0) {
            if (!vis[i]) {
                vis[i]=1;
                ++ret;
                FOR(j,D,i) 
                    FOR(k,R,j) 
                        vis[col[k]] = 1;
            }
        }
        return ret;
    } 
    bool dfs(int d) {
        if ( R[0] == 0) {
            ansd = d;
            return 1;
        } 
        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 1;
            FOR(j,L,i) restore(col[j]);
        } 
        restore(c);
        return 0;
    }   
    bool solve(vi &v) {
        v.clear();
        if (!dfs(0)) return 0;
        Rep(i,ansd) v.pb(ans[i]);
        return 1;
    }   
};
#define MAXN (60+10)
DLX solver;
int n,m,d;
bool f[MAXN][MAXN];
int l[MAXN],r[MAXN];
int ansl[MAXN],ansr[MAXN];
const int seg[16][2]={{1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5},
{2, 2}, {2, 3}, {2, 4}, {2, 5},
{3, 3}, {3, 4}, {3, 5},
{4, 4}, {4, 5},
{5, 5}, {0, 0}};
int main()
{
//  freopen("hdu3663.in","r",stdin);
//  freopen("hdu3663.out","w",stdout);

    while(cin>>n>>m>>d) {
        solver.init(n*d+n);
        MEM(f)
        Rep(i,m) {
            int u=read(),v=read();
            f[u][v]=f[v][u]=1;
        }
        For(i,n) {
            f[i][i]=1;
            cin>>l[i]>>r[i];
        }
        For(i,n) {
            Rep(j,15) {
                int u=(i-1)*16+j+1;
                vi columns;
                if (l[i]<=seg[j][0] && seg[j][1]<=r[i] ) {
                    For(k,n) {
                        if (f[i][k])
                            Fork(l2,seg[j][0],seg[j][1])
                            {
                                int v=(k-1)*d+l2;
                                columns.pb(v);
                            }
                    }
                    columns.pb(n*d+i);
                    solver.addRow(u,columns);
                }
            }
            vi columns;
            columns.pb(n*d+i);
            solver.addRow(16*i,columns);
        }
        vi v;
        bool flag=solver.solve(v);
        if(!flag) {
            puts("No solution"); puts("");continue;
        }
        int sz=SI(v);
        MEM(ansl) MEM(ansr)
        Rep(i,sz) {
            int u=v[i];
            int x=1+(u-1)/16 , y =(u-1)%16; 
            ansl[x]= seg[y][0];
            ansr[x]= seg[y][1];
        }
        For(i,n) printf("%d %d\n",ansl[i],ansr[i]);
        puts("");
    }
    return 0;
}

FZU 1686 神龙的难题

题目大意:有n*m的01矩阵,1代表有怪物,神龙的攻击范围为n1*m1的矩阵,一次攻击可以把这个范围内的怪物全部消灭,最少攻击几次,把所有的怪物全都灭掉?

#pragma comment(linker, "/STACK:102400000,102400000")  
#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <queue>  
#include <stack>  
#include <set>  
#include <map>  
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 
int ans=0;
struct DLX {
    #define MAXNode (1000000+10)
    #define maxn (1000000+10)
    #define maxm (1000+10) 
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];
    int sz,col[MAXNode],S[maxm],H[maxn];
    bool vis[maxm];
    void init(int m) {
        Rep(i,m+1) {
            L[i] = i-1;
            R[i] = i+1;
            U[i] = D[i] =i;
            S[i] = 0;
        } 
        memset(H,-1,sizeof(H));
        L[0]=m; R[m] = 0;
        sz=m+1;
    } 
    #define FOR(i,A,s) for(int i=A[s];i!=s;i=A[i])   
    void remove(int c) {
        FOR(i,D,c) {
            L[R[i]] = L[i];
            R[L[i]] = R[i];
        }
    } 
    void resume(int c) {
        int i; 
        for(int i=U[c];i!=c;i=U[i]) {
            L[R[i]] = R[L[i]] = i;
        }
    } 
    void link(int r,int c) {
        U[sz] = c;
        D[sz] = D[c];
        U[D[c]] = sz;
        D[c] = sz;
        if (H[r]==-1) { H[r]=L[sz]=R[sz]=sz;    }
        else {
            L[sz] =H[r];
            R[sz] = R[H[r]];
            L[R[H[r]]] = sz;
            R[H[r]] = sz;
        } 
        S[c]++ ; col[sz++]=c;
    } 
    int A() {
        MEM(vis)
        int res=0;
        FOR(i,R,0) {
            if (!vis[i]) {
                res++;
                vis[i] = 1;
                FOR(j,D,i) FOR(k,R,j) {
                    vis[col[k]]=1;
                } 
            } 
        } 
        return res;
    }
    void dfs(int d) {
        if (!R[0])  {
            ans=min(ans,d);
        } else if (d+A()<ans) {
            int c=R[0];
            FOR(i,R,0) {
                if (S[i]<S[c]) c=i;
            } 
            FOR(i,D,c) {
                remove(i);
                FOR(j,R,i) remove(j);
                dfs(d+1);
                FOR(j,L,i) resume(j);
                resume(i);
            } 
        } 
    } 
}solver; 
#define MAXN (30)
int h[MAXN][MAXN];
int main()
{
//  freopen("fzu1686.in","r",stdin);
//  freopen(".out","w",stdout);

    int n,m;
    while(cin>>n>>m) {
        int cm=0;
        For(i,n) For(j,m) {
            int p=read();
            if (p==1) h[i][j]=++cm;
            else h[i][j]=-1;
        }
        solver.init(cm);
        int n1=read(),m1=read();
        For(i,n-n1+1) {
            For(j,m-m1+1) {
                int u=(i-1)*m+j;
                Fork(k,i,i+n1-1)
                    Fork(l,j,j+m1-1) {
                        if (h[k][l]!=-1) solver.link(u,h[k][l]);
                    }
            }
        } 
        ans=INF;
        solver.dfs(0);      
        cout<<ans<<endl;
    }

    return 0;
}

NOIP 2009 靶形数独

#include<bits/stdc++.h>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=Pre[x];p;p=Next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define pb push_back
#define mp make_pair 
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
                        For(j,m-1) cout<<a[i][j]<<' ';\
                        cout<<a[i][m]<<endl; \
                        } 
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
    int x=0,f=1; char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
    return x*f;
} 

const int p[9][9] = {
{6,6,6,6,6,6,6,6,6},
{6,7,7,7,7,7,7,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,9,10,9,8,7,6},
{6,7,8,9,9,9,8,7,6},
{6,7,8,8,8,8,8,7,6},
{6,7,7,7,7,7,7,7,6},
{6,6,6,6,6,6,6,6,6}
};
int encode(int a,int b,int c) {
    return a*81+b*9+c+1;
}
void decode(int code,int &a,int &b,int &c) {
    code--;
    c=code%9; code/=9;
    b=code%9; code/=9;
    a=code;
}
int ans=0;
struct DLX {
    #define maxn (10000000+10)
    #define MAXNode (10000000+10)
    #define maxr (10000000)
    int n, sz;
    int S[maxn];
    int row[MAXNode],col[MAXNode];
    int L[MAXNode],R[MAXNode],U[MAXNode],D[MAXNode];

    void init(int n) {
        this->n = n;
        Rep(i,n+1) {
            U[i] = D[i] = i ; L[i]=i-1; R[i]=i+1;
        }
        R[n]=0; L[0]=n;
        sz=n+1;
        MEM(S)
    }

    void addRow(int r, vi columns) {
        int fir = sz;
        int cSz=columns.size();
        Rep(i,cSz) {
            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]=fir; L[fir] = 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,int l) {
        if ( R[0] == 0) {
            ans = max(ans,l);return;
        } 
        int c = R[0];
        FOR(i,R,0) if (S[i] < S[c]) c = i;
        remove(c);
        FOR(i,D,c) {
            FOR(j,R,i) remove(col[j]);

            int rr,cc,vv;
            decode(row[i],rr,cc,vv); 

            dfs(d+1,l+(1+vv)*p[rr][cc]  );
            FOR(j,L,i) restore(col[j]);
        } 
        restore(c);
    }   
    void solve() {
        dfs(0,0);
    }   
};
DLX solver;
int puzzle[9][9];
void init() {
    Rep(i,9) {
        Rep(j,9) cin>>puzzle[i][j];
    }
}
const int SLOT = 0;
const int ROW = 1;
const int COL = 2;
const int SUB = 3;

int main()
{
//  freopen("vijosP1755.in","r",stdin);
//  freopen(".out","w",stdout);
    init();
    solver.init(81*4); //列数要初始化  
    Rep(r,9) Rep(c,9) Rep(v,9) { // put v in (r,c)
        if (puzzle[r][c]==0||puzzle[r][c]==1+v) {
            vi columns;
            columns.pb(encode(SLOT,r,c));
            columns.pb(encode(ROW,r,v));
            columns.pb(encode(COL,c,v));
            columns.pb(encode(SUB,r/3*3+c/3,v));
            solver.addRow(encode(r,c,v),columns);
        } 
    }
    ans=0;
    solver.solve();
    if (!ans) puts("-1");
    else cout<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值