HDU -- 3287 Theta Puzzle - xIao_wU 思维磁场 - Just Run And Never Forget I Have A Dream

HDU -- 3287 Theta Puzzle

xIao.wU posted @ 2010年2月01日 19:57 in 搜索 , 1746 阅读

    有7个点 , 可以给每个点编号 , 分别为0~6 , 故这个图共有 7! = 5040 种状态量,这个状态量可以很灵活的实现 , 而且要超时基本是不可能的 , 判重方面可以适用全排列的hash , 故内存也占极少 , 所以适用任何一种算法。
   状态转移则可以适用
   int move[7][3] = { {1 , 5} , {0 , 2 , 6} , {1 , 3} , {2 , 4} , {3 , 5 , 6} , {0 , 4} , {1 , 4} };
   若move[j] 则表示 i点和j点可互换 , i 点为这个游戏的空点。
   开多一个数组来存可以移动个数
   int dir[7] = {2 , 3 , 2 , 2 , 3 , 2 , 2};

#include <iostream> 
using namespace std; 

const int N = 5041; 
const int SIZE = 1000000; 

int mat[7] , fac[7] , f[N]; // fac为阶乘 , f记录父节点 , step数组用于记录交换对象 
char op[7] , step[N]; 
bool hash[N]; 
int dir[7] = {2 , 3 , 2 , 2 , 3 , 2 , 2}; 
int move[7][3] = { {1 , 5} , {0 , 2 , 6} , {1 , 3} , {2 , 4} , {3 , 5 , 6} , {0 , 4} , {1 , 4} }; 
struct node { 
       int state[7]; 
       int step , pos , key; //状态 , 步数 , 关键点 , 关键字 
} Que[SIZE]; 

int get_key(int s[]) {     //全排列 hash , 得到关键字 
       int ret = 0 , count; 
       for(int i=1; i < 7; i++) { 
           count = 0; 
           for(int j=0; j < i; j++) 
               count += s[j] > s[i] ? 1 : 0; 
           ret += count * fac[i]; 
       } 
       return ret; 
} 

void search(int x) { //回溯 
       if(f[x] == -1) return ; 
       search(f[x]); 
       printf("%c" , step[x]); 
} 

void solve() { 
       int key = get_key(mat); 
       hash[key] = 1; 
       if(key == 0) { 
               printf("0\n"); 
               return ; 
       } 
       f[key] = -1; 
       node T; 
       for(int i=0; i < 7; i++) T.state[i] = mat[i]; 
       T.pos = 6 , T.step = 0 , T.key = key; 
       int head = 0 , tail = 0; 
       Que[tail ++] = T; //T乃头结点 
       while(head != tail) { 
               node x1 , x2; 
               x1 = Que[head];  //循环队列, 个人习惯。。 
               head = (head + 1) % SIZE; 
               int num = dir[x1.pos]; 
               for(int i=0; i < 7; i++) 
                       x2.state[i] = x1.state[i] ; 
               int a = x1.pos; 
               int cnt; 
               for(int i=0; i < num; i++) { 
                       cnt = x2.state[move[a][i]]; 
                       swap(x2.state[a] , x2.state[move[a][i]]); 
                       x2.pos = move[a][i]; 
                       x2.step = x1.step + 1; 
                       key = get_key(x2.state); 
                       if(key == 0) { 
                               printf("%d " , x2.step); 
                               f[key] = x1.key; 
                               step[key] = cnt + 'A'; 
                               search(0); 
                               puts(""); 
                               return ; 
                       } 
                       if(!hash[key]) { 
                               hash[key] = 1; 
                               x2.key = key; 
                               f[x2.key] = x1.key; 
                               step[x2.key] = cnt + 'A'; 
                               Que[tail] = x2; 
                               tail = (tail + 1) % SIZE; 
                       } 
                       swap(x2.state[a] , x2.state[move[a][i]]); 
               } 
       } 
       printf("NO SOLUTION\n"); 
} 

void init() { //初始化 
       fac[1] = 1; 
       for(int i=2; i < 7; i++) 
               fac[i] = fac[i - 1] * i; 
       memset(hash , 0 , sizeof(hash)); 
       memset(f , -1 , sizeof f); 
} 

int main() { 
       //freopen("in.txt" , "r" , stdin); 
       int p , t; 
       scanf("%d" , &p); 
       while(p --) { 
               scanf("%d %s" , &t , op); 
               printf("%d " , t); 
               for(int i=0; i < 6; i++) 
                       mat[i] = op[i] - 'A'; 
               mat[6] = 6; 
               init(); 
               solve(); 
       } 
       return 0; 
} 

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter
Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee