zoukankan      html  css  js  c++  java
  • POJ 3074

    同上题

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <string.h>
    #include <vector>
    using namespace std;
    
    int puzzle[10][10];
    char tmp[100];
    const int SLOT=0;
    const int ROW=1;
    const int COL=2;
    const int SUB=3;
    const int maxn=400;
    const int maxnode=9*9*9*9*9*4+100;
    const int maxr=9*9*9*9*9*4+100;
    
    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[maxn];                                         // 解
    
      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> c1)
      {
        int first = sz;
        for(int i = 0 ; i < c1.size(); i++ ){
          int c = c1[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;
      }
      // 顺着链表A,遍历除s外的其他元素
      #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;
        }
        // 找S最小的列c
        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;
      }
    };
    DLX slover;
    
    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;
    }
    
    bool read(){
    	scanf("%s",tmp);
    	if(strcmp(tmp,"end")==0) return false;
    	for(int i=0;i<9;i++){
    		for(int j=0;j<9;j++){
    			if(tmp[i*9+j]=='.')
    			puzzle[i][j]=0;
    			else	puzzle[i][j]=tmp[i*9+j]-'0';
    		}
    	}
    	return true;
    }
    
    int main(){
    	while(read()){
    		slover.init(324);
    		for(int r=0;r<9;r++){
    			for(int c=0;c<9;c++){
    				for(int v=0;v<9;v++){
    					if(puzzle[r][c]==0||puzzle[r][c]==v+1){
    						vector<int> columns;
    						columns.push_back(encode(SLOT,r,c));
    						columns.push_back(encode(ROW,r,v));
    						columns.push_back(encode(COL,c,v));
    						columns.push_back(encode(SUB,(r/3)*3+c/3,v));
    						slover.addRow(encode(r,c,v),columns);
    					}
    				}
    			}
    		}
    		vector<int>ans;
    		slover.solve(ans);
    		for(int i=0;i<ans.size();i++){
    			int r,c,v;
    			decode(ans[i],r,c,v);
    			puzzle[r][c]=v+1;
    		}
    		for(int i=0;i<9;i++){
    		for(int j=0;j<9;j++)
    		printf("%d",puzzle[i][j]);
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3934542.html
Copyright © 2011-2022 走看看