POJ2965解题报告(BFS,位压缩)

来源:互联网 发布:淘宝联盟怎么登录 编辑:程序博客网 时间:2024/05/16 15:37

因为和之前的翻转问题十分类似,思想就不列举了,贴上代码,供以后温故:

#include <iostream>#include<fstream>#include<cstdlib>#include<cstring>#include<cstdio>#include<queue>#include<stack>using namespace std;const int MAX = 16;int final_step = MAX;const int MAX_STATE = 65536;int flips[4][4] = {4383, 8751, 17487, 34959, 4593, 8946, 17652, 35064, 7953, 12066, 20292, 36744, 61713, 61986, 62532, 63624};  struct POINT{int x;int y;};POINT pts[MAX_STATE];int states[MAX_STATE];int steps[MAX_STATE];int pres[MAX_STATE];int qu[MAX_STATE];int init(char str[]){int current_state = 0;for(int i=0;i<MAX;i++){if(str[i] == '+'){current_state += (1 << i);}}return current_state;}int flip(int state,int x,int y){state ^= flips[x][y];return state;}void ans(int current_state){memset(steps,0,sizeof(steps));memset(states,0,sizeof(states));memset(pres,0,sizeof(pres));states[current_state] = 1;steps[current_state] = 0;pres[current_state] = 0;pts[current_state].x = -1;pts[current_state].y = -1;int front =0;int tail = 0;tail ++;qu[front] = current_state;int final_step = 0;while(true){int cur = qu[front++];if(cur == 0){break;}for(int i=0;i<4;i++){for(int j=0;j<4;j++){int next  = flip(cur,i,j);if(!states[next]){states[next] = 1;steps[next] = steps[cur] + 1;pres[next] = cur;pts[next].x = i;pts[next].y = j;qu[tail++] = next;}}}}cout << steps[0] <<endl;stack<int> st;int tmp = 0;while(pres[tmp] != current_state){st.push(tmp);tmp = pres[tmp];}st.push(tmp);while(st.size()>0){cout << pts[st.top()].x + 1 <<' ' << pts[st.top()].y + 1 <<endl;st.pop();}}int main(int argc, char** argv) {//ifstream cin("L:/test.txt");char str[MAX];int number = 0;char c;while(cin >> c){if(c==' ' || c == '\n') continue; str[number++] = c; if(number == 16) break;}int current_state = init(str);ans(current_state);//system("pause");return 0;}

主要的点在于翻转控制,毕竟BFS太简单了,而且用queue的时候会有问题,自己定义队列最好!


对于位压缩的这些常量值,整理了一下思路,写出了下面的代码,可以对照,在表中出现的值,和相应的执行代码:

/*** 位分布图(每一位对应于原题中该位置)* 0  1  2  3* 4  5  6  7* 8  9  10 11* 12 13 14 15*/#include<iostream>#include<cstdlib>#include<vector>using namespace std;const int row[] = {0xF,0XF0,0XF00,0XF000};void binary(int num){vector<int> v;int yu = num % 2;while(num / 2){yu = num % 2;v.push_back(yu);num = num / 2;}v.push_back(1);while(v.size() <16){v.push_back(0);}for(int i=1;i<=16;i++){cout << v[i-1];if(i % 4 == 0)cout <<endl;}cout <<endl;}int main(){int state = 0;int count = -1;for(int i=0;i<4;i++){for(int j=0;j<4;j++){count ++;state = 0;state ^=  row[i];state ^= (1 <<count);//行列交汇处异或之后复原了,要补上这一步!!!switch(j){case 0:state ^= ((1<<0) + (1<<4) + (1<<8) +( 1<< 12));break;case 1:state ^= ((1<<1) + (1<<5) + (1<<9) + ( 1<< 13));break;case 2:state ^= ((1<<2) + (1<<6) + (1<<10) +( 1<< 14));break;case 3:state ^= ((1<<3) + (1<<7) + (1<<11) +( 1<< 15));break;}cout << count <<" : " <<state <<endl;binary(state);}}//system("pause");return 0;}
binary 把每个数字对应在原图中对应的位置标识了出来,非常直观!

0 0
原创粉丝点击