Eight poj1077 广度优先搜索

来源:互联网 发布:java抢票软件开发源码 编辑:程序博客网 时间:2024/05/19 03:29

http://poj.org/problem?id=1077

这个题在poj用朴素的算法就可以了。

在hdu上需要用双向广搜才可以。

首先贴一个单向广搜。

#include <iostream>#include <bitset>using namespace std;int nGoalStatus;//目标状态/*声明了一个含有9!个位的bitset对象,位的顺序从0到31,缺省情况下所有的位都被初始化为0 */bitset<362880> Flags; //节点是否标记char szResult[400000];//结果char szMoves[400000];//移动步骤 u/d/r/lint anFather[400000];//父节点指针int MyQueue[400000];//状态队列,状态总数362880int nQHead,nQTail;char sz4Moves[]="udrl";//四种动作template<class T>unsigned int GetPermutationNum(T *first,T *permutation,int len){//permutation编号从0开始算,[first,first+len)里面存放着第0号permutation,排列的每个元素都不一样,返回排列的编号unsigned int factorial[21]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,1932053504,1278945280,2004310016,2004189184,4006445056,3396534272,109641728,2192834560};bool used[21] = {0};int perInt[21]; //要转换成[0,len-1]的整数的排列for(int i=0;i<len;++i)for( int j=0; j<len;++j){if(*(permutation+i) == *(first+j)){perInt[i]=j;break;}}unsigned int num=0;for( int i=0;i<len;++i){unsigned int n=0;for( int j=0;j<perInt[i];++j){if(!used[j]) ++n;}num+=n*factorial[len-i-1];used[perInt[i]]=true;}return num;}template <class T>void GenPermutationByNum(T *first,T *permutation,int len,unsigned int No){ //根据排列编号,生成排列//[first,first+len) 里面放着第0号 permutation,,排列的每个元素都不一样unsigned int factorial[21] ={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,1932053504,1278945280,2004310016,2004189184,4006445056,3396534272,109641728,2192834560};bool used[21]={0};int perInt[21]; //要转换成 [0,len-1] 的整数的排列for(int i=0;i<len;++i){unsigned int tmp;int n=0;int j;for(j=0;j<len;++j){if(!used[j]){if(factorial[len-i-1]>= No+1)break;else No-=factorial[len-i-1];}}perInt[i]=j;used[j]=true;}for(int i=0;i<len;++i) *(permutation+i)=*(first+perInt[i]);}int StrStatusTointStatus(const char *strStatus){return GetPermutationNum("012345678",strStatus,9);}void IntStatusToStrStatus(int n,char *StrStatus){GenPermutationByNum((char *)"012345678",StrStatus,9,n);}int NewStatus(int nStatus,char cMove){//求从nStatus经过cMove移动后得到的新状态。若移动不可行则返回-1char szTmp[20];int nZeroPos;IntStatusToStrStatus(nStatus,szTmp);int i;for (i=0;i<9;i++){if (szTmp[i]=='0'){nZeroPos=i;break;}}//返回空格的位置switch(cMove){case 'u':if (nZeroPos-3<0)return -1;//空格在第一行else{szTmp[nZeroPos]=szTmp[nZeroPos-3];szTmp[nZeroPos-3]='0';}break;case 'd':if (nZeroPos+3>8)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos+3];szTmp[nZeroPos+3]='0';}break;case 'l':if(nZeroPos%3==0)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos-1];szTmp[nZeroPos-1]='0';}break;case 'r':if (nZeroPos%3==2)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos+1];szTmp[nZeroPos+1]='0';}}return StrStatusTointStatus(szTmp);}bool Bfs(int nStatus){int nNewStatus,i;Flags.reset();//将所有位置0nQHead=0;nQTail=1;MyQueue[nQHead]=nStatus;while (nQHead!=nQTail){//队列不为空nStatus=MyQueue[nQHead];if (nStatus==nGoalStatus)return true;for (i=0;i<4;i++){nNewStatus=NewStatus(nStatus,sz4Moves[i]);if(nNewStatus==-1)continue;if (Flags[nNewStatus])continue;Flags.set(nNewStatus,true);MyQueue[nQTail]=nNewStatus;anFather[nQTail]=nQHead;//记录父节点//记录本节点是由父节点经什么动作而来szMoves[nQTail]=sz4Moves[i];nQTail++;}nQHead++;}return false;}int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endifnGoalStatus=StrStatusTointStatus("123456780");char szLine[50];char szLine2[20];while (cin.getline(szLine,48)){int i,j;//将输入的原始字符串变为九进制字符串for (i=0,j=0;szLine[i];i++)if(szLine[i]!=' '){if(szLine[i]=='x')szLine2[j++]='0';else szLine2[j++]=szLine[i];}szLine2[j]='\0';/*接下来的步骤用来判断该串是否有解 偶序列和奇序列不能相互转换。只能目标序列和源序列同为奇序列或者偶序列才可能有解决方案。*/int sumGoal=0;for (i=0;i<8;i++)sumGoal+=i-1;int sumOri=0;for (i=0;i<9;i++){if(szLine2[i]=='0')continue;for(j=0;j<i;j++)if(szLine2[j]<szLine2[i]&&szLine2[j]!='0')sumOri++;}if (sumOri%2!=sumGoal%2){cout<<"unsolvable"<<endl;continue;}if(Bfs(StrStatusTointStatus(szLine2))){int nMoves=0;int nPos=nQHead;do{ //通过anFather数组找到成功的状态序列,输出相应步骤szResult[nMoves++]=szMoves[nPos];nPos=anFather[nPos];}while (nPos);for(i=nMoves-1;i>=0;i--)cout<<szResult[i];cout<<endl;}else cout<<"unsolvable"<<endl;}}

然后再 粘一个双向广搜。

下面的代码可以过hdu1043,上面的代码过不去...

#include <iostream>#include <bitset>using namespace std;int nGoalStatus;//目标状态/*声明了一个含有9!个位的bitset对象,位的顺序从0到31,缺省情况下所有的位都被初始化为0 */bitset<362880> Flags[2]; //节点是否标记char szResult[400000];//结果char szMoves[2][400000];//移动步骤 u/d/r/lint anFather[2][400000];//父节点指针int Queue[2][400000];//状态队列,状态总数362880int QHead[2],QTail[2];char sz4Moves[]="udrl";//四种动作int matchingStatus;//双向碰到的那个状态int matchingQ;//队列matchingQ的对头元素是双向碰到的那个状态template<class T>unsigned int GetPermutationNum(T *first,T *permutation,int len){//permutation编号从0开始算,[first,first+len)里面存放着第0号permutation,排列的每个元素都不一样,返回排列的编号unsigned int factorial[21]={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,1932053504,1278945280,2004310016,2004189184,4006445056,3396534272,109641728,2192834560};bool used[21] = {0};int perInt[21]; //要转换成[0,len-1]的整数的排列for(int i=0;i<len;++i)for( int j=0; j<len;++j){if(*(permutation+i) == *(first+j)){perInt[i]=j;break;}}unsigned int num=0;for( int i=0;i<len;++i){unsigned int n=0;for( int j=0;j<perInt[i];++j){if(!used[j]) ++n;}num+=n*factorial[len-i-1];used[perInt[i]]=true;}return num;}template <class T>void GenPermutationByNum(T *first,T *permutation,int len,unsigned int No){ //根据排列编号,生成排列//[first,first+len) 里面放着第0号 permutation,,排列的每个元素都不一样unsigned int factorial[21] ={1,1,2,6,24,120,720,5040,40320,362880,3628800,39916800,479001600,1932053504,1278945280,2004310016,2004189184,4006445056,3396534272,109641728,2192834560};bool used[21]={0};int perInt[21]; //要转换成 [0,len-1] 的整数的排列for(int i=0;i<len;++i){unsigned int tmp;int n=0;int j;for(j=0;j<len;++j){if(!used[j]){if(factorial[len-i-1]>= No+1)break;else No-=factorial[len-i-1];}}perInt[i]=j;used[j]=true;}for(int i=0;i<len;++i) *(permutation+i)=*(first+perInt[i]);}int StrStatusTointStatus(const char *strStatus){return GetPermutationNum("012345678",strStatus,9);}void IntStatusToStrStatus(int n,char *StrStatus){GenPermutationByNum((char *)"012345678",StrStatus,9,n);}int NewStatus(int nStatus,char cMove){//求从nStatus经过cMove移动后得到的新状态。若移动不可行则返回-1char szTmp[20];int nZeroPos;IntStatusToStrStatus(nStatus,szTmp);int i;for (i=0;i<9;i++){if (szTmp[i]=='0'){nZeroPos=i;break;}}//返回空格的位置switch(cMove){case 'u':if (nZeroPos-3<0)return -1;//空格在第一行else{szTmp[nZeroPos]=szTmp[nZeroPos-3];szTmp[nZeroPos-3]='0';}break;case 'd':if (nZeroPos+3>8)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos+3];szTmp[nZeroPos+3]='0';}break;case 'l':if(nZeroPos%3==0)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos-1];szTmp[nZeroPos-1]='0';}break;case 'r':if (nZeroPos%3==2)return -1;else {szTmp[nZeroPos]=szTmp[nZeroPos+1];szTmp[nZeroPos+1]='0';}}return StrStatusTointStatus(szTmp);}char ReverseMove(char c){switch(c){case 'u':return 'd';case 'l':return 'r';case 'r':return 'l';case  'd':return 'u';}return 0;}bool DBfs(int nStatus){int nNewStatus;int i;for (i=0;i<2;i++){Flags[i].reset();QHead[i]=0;QTail[i]=1;}Queue[0][0]=nStatus;Queue[1][0]=nGoalStatus;Flags[0][nStatus]=1;Flags[1][nGoalStatus]=1;while (QHead[0]!=QTail[0]&&QHead[1]!=QTail[1]){int qNo;if(QHead[0]==QTail[0])qNo=1;else if(QHead[1]==QTail[1])qNo=0;else{if (QHead[0]-QTail[0]>QHead[1]-QTail[1])qNo=0;else qNo=1; }int vqNo=1-qNo;nStatus=Queue[qNo][QHead[qNo]];if (Flags[vqNo][nStatus]==1){//取出的元素曾在另一队列出现过matchingStatus=nStatus;matchingQ=qNo;return true;}else {for (i=0;i<4;i++){nNewStatus=NewStatus(nStatus,sz4Moves[i]);if (nNewStatus==-1)continue;if (Flags[qNo][nNewStatus])continue;Flags[qNo][nNewStatus]=1;Queue[qNo][QTail[qNo]]=nNewStatus;anFather[qNo][QTail[qNo]]=QHead[qNo];szMoves[qNo][QTail[qNo]]=sz4Moves[i];QTail[qNo]++;}QHead[qNo]++;}}return false;}int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);#endifnGoalStatus=StrStatusTointStatus("123456780");char szLine[50];char szLine2[20];while (cin.getline(szLine,48)){int i,j;//将输入的原始字符串变为九进制字符串for (i=0,j=0;szLine[i];i++)if(szLine[i]!=' '){if(szLine[i]=='x')szLine2[j++]='0';else szLine2[j++]=szLine[i];}szLine2[j]='\0';/*接下来的步骤用来判断该串是否有解 偶序列和奇序列不能相互转换。只能目标序列和源序列同为奇序列或者偶序列才可能有解决方案。*/  int sumGoal=0;for (i=0;i<8;i++)sumGoal+=i-1;int sumOri=0;for (i=0;i<9;i++){if(szLine2[i]=='0')continue;for(j=0;j<i;j++)if(szLine2[j]<szLine2[i]&&szLine2[j]!='0')sumOri++;}if (sumOri%2!=sumGoal%2){cout<<"unsolvable"<<endl;continue;}if(DBfs(StrStatusTointStatus(szLine2))){int nMoves=0;int Pos,i;if (matchingQ==0)Pos=QHead[0];else {for (i=0;i<QTail[0];i++)if (Queue[0][i]==matchingStatus){Pos=i;break;}}do {if (Pos){szResult[nMoves++]=szMoves[0][Pos];Pos=anFather[0][Pos];}}while (Pos);reverse(szResult,szResult+nMoves);if (matchingQ==0){for (i=0;i<QTail[1];i++)if (Queue[1][i]==matchingStatus){Pos=i;break;}}else Pos=QHead[1];do {if (Pos){szResult[nMoves++]=ReverseMove(szMoves[1][Pos]);Pos=anFather[1][Pos];}}while(Pos);for (i=0;i<nMoves;i++)cout<<szResult[i];cout<<endl;}else cout<<"unsolvable"<<endl;}return 0;}


原创粉丝点击