1. 程式人生 > >HDU - 1043 - Eight(經典八數碼&&各種搜尋) (未完)

HDU - 1043 - Eight(經典八數碼&&各種搜尋) (未完)

關於逆序數判別是否有解

單向BFS

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,char> pic;

struct Node
{
    int s[9];//當前排列
    int ri,ci;//x的位置
    int status;//狀態的康拓對映
    int cnt;//移動步數
    Node()
    {
        memset(s,0,sizeof(s));
        ri=ci=0;
        status=-1;
        cnt=0;
    }
};
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};//

char in[20];
Node st,ed;
queue<Node> Q;
int fac[9];
bool vis[(int)4e5+10];
map<int,pair<int,int> >pre;//記錄路徑

bool InMap(int ri,int ci)
{
    return ri>=0&&ri<3&&ci>=0&&ci<3;
}

int Cantor(int s[])//康拓展開求排列序號
{
    int ret=0;
    for(int i=0; i<9; i++)
    {
        int cnt=0;
        for(int j=i+1; j<9; j++)
        {
            if(s[j]<s[i])cnt++;
        }
        ret+=cnt*fac[8-i];
    }
    return ret;
}

int BFS(const Node& st,int edval)
{
    memset(vis,false,sizeof(vis));
    while(!Q.empty())Q.pop();
    pre.clear();
    Q.push(st);
    vis[st.status]=true;
    pre[st.status]=make_pair(-1,-1);
    while(!Q.empty())
    {
        Node u=Q.front();
        Q.pop();
        if(u.status==edval)return u.cnt;
        for(int di=0; di<4; di++)
        {
            Node v=u;
            v.ri=u.ri+dir[di][0];
            v.ci=u.ci+dir[di][1];
            if(!InMap(v.ri,v.ci))continue;
            int upos=3*u.ri+u.ci;
            int vpos=3*v.ri+v.ci;
            swap(v.s[upos],v.s[vpos]);
            v.status=Cantor(v.s);
            if(vis[v.status])continue;
            vis[v.status]=true;
            v.cnt=u.cnt+1;
            Q.push(v);
            pre[v.status]=make_pair(u.status,di);
            if(v.status==edval)return v.cnt;
        }
    }
    return -1;
}

int main()
{
    fac[0]=1;
    for(int i=1; i<9; i++)fac[i]=i*fac[i-1];
    ed.ri=ed.ci=2;
    for(int i=0; i<9; i++)
    {
        ed.s[i]=i+1;
    }
    ed.status=Cantor(ed.s);
    while(cin>>in[0])
    {
        for(int i=1; i<9; i++)cin>>in[i];
        for(int ri=0; ri<9; ri++)
        {
            if('x'==in[ri])
            {
                st.s[ri]=9;
                st.ri=ri/3;
                st.ci=ri%3;
            }
            else st.s[ri]=in[ri]-'0';
        }
        st.status=Cantor(st.s);
        st.cnt=0;
        int flag=BFS(st,ed.status);
        if(-1==flag)puts("unsolvable");
        else
        {
            char ans[1000];
            char ch[5]="udlr";//與dir方向對應
            int k=ed.status;
            ans[flag]=0;
            while(k!=st.status)
            {
                flag--;
                ans[flag]=ch[pre[k].second];
                k=pre[k].first;
            }
            puts(ans);
        }
    }
    return 0;
}

雙向BFS

http://www.cnblogs.com/bofengyu/p/4825529.html

#include <bits/stdc++.h>
using namespace std;
const int maxn = 362885;  //狀態數9!
int dir[4] = {-3,3,-1,1}; //某個方向移動對應一維的位置變化
char opf[4] = {'u','d','l','r'};//正向bfs對應的
char opr[4] = {'d','u','r','l'};
int fac[9] = {1,1,2,6,24,120,720,5040,40320};//康拓展開
bool visf[maxn];//標記正向狀態是否訪問
bool visr[maxn];
string targs = "123456789";//目標狀態
struct Node
{
    string s;
    int xloca;
} node;
struct Node2
{
    int idf,idr;//正向前驅和後驅
    char cf,cr;//對應的操作
} op[maxn];
int cantor(string s)//求排列對應的康拓展開
{
    int num = 0;
    for(int i = 0; i < 9; i++)
    {
        int t = 0;
        for(int j = i + 1; j < 9; j++)
        {
            if(s[j] < s[i])
                t++;
        }
        num += fac[8-i] * t;
    }
    return num;
}
void print(int i)//遞迴輸出
{
    if(op[i].idf == -1) return;
    print(op[i].idf);
    cout<<op[i].cf;
}
void DoubleBFS()
{
    queue<Node> qf,qr;
    Node t1,t2;
    int hash1,hash2,xloca;
    t1 = node;   //初始狀態
    t2.s = targs;//目標狀態.
    t2.xloca = 8;//目標狀態x位置
    hash1 = cantor(t1.s);
    visf[hash1] = true;
    op[hash1].idf = -1;
    qf.push(t1);
    hash1 = cantor(t2.s);
    visr[hash1] = true;
    op[hash1].idr = -1;
    qr.push(t2);
    while(!qf.empty()&&!qr.empty())
    {
        //正向bfs
        t1 = qf.front();
        qf.pop();
        hash1 = cantor(t1.s);
        if(visr[hash1])
        {
            print(hash1);
            hash2 = hash1;
            while(op[hash2].idr != -1)
            {
                cout<<op[hash2].cr;
                hash2 = op[hash2].idr;
            }
            cout<<endl;
            return ;
        }
        for(int i = 0; i < 4; i++)
        {
            if(i == 0 && t1.xloca < 3) continue;
            if(i == 1 && t1.xloca > 5) continue;
            if(i == 2 && t1.xloca%3 == 0) continue;
            if(i == 3 && t1.xloca%3 == 2) continue;
            xloca = t1.xloca + dir[i];
            t2 = t1;
            swap(t2.s[t1.xloca],t2.s[xloca]);
            hash2 = cantor(t2.s);
            if(!visf[hash2])
            {
                visf[hash2] = true;
                t2.xloca = xloca;
                op[hash2].idf = hash1;
                op[hash2].cf = opf[i];
                qf.push(t2);
            }
        }
        //反向bfs
        t1 = qr.front();
        qr.pop();
        hash1 = cantor(t1.s);
        if(visf[hash1])
        {
            print(hash1);
            hash2 = hash1;
            while(op[hash2].idr != -1)
            {
                cout<<op[hash2].cr;
                hash2 = op[hash2].idr;
            }
            cout<<endl;
            return;
        }

        for(int i = 0; i < 4; i++)
        {
            if(i == 0 && t1.xloca < 3) continue;
            if(i == 1 && t1.xloca > 5) continue;
            if(i == 2 && t1.xloca%3 == 0) continue;
            if(i == 3 && t1.xloca%3 == 2) continue;
            xloca = t1.xloca + dir[i];
            t2 = t1;
            swap(t2.s[t1.xloca],t2.s[xloca]);
            hash2 = cantor(t2.s);
            if(!visr[hash2])
            {
                visr[hash2] = true;
                t2.xloca = xloca;
                op[hash2].idr = hash1;
                op[hash2].cr = opr[i];
                qr.push(t2);
            }
        }
    }
}
int main()
{
    string str;
    int len;
    int ivsNum;//逆序數
    while(getline(cin,str))
    {
        memset(visf,0,sizeof visf);
        memset(visr,0,sizeof visr);
        len = str.size();
        node.s = "";
        int k = 0;
        for(int  i = 0; i < len; i++)
        {
            if(str[i]!=' ')
            {
                if(str[i] == 'x')
                {
                    node.s = node.s + '9';
                    node.xloca = k;
                }
                else
                {
                    node.s = node.s + str[i];
                }
                k++;
            }
        }
        //cout<<node.s<<endl;
        ivsNum = 0;
        for(int  i = 0; i < 9; i++)
        {
            if(node.s[i] == '9') continue;
            for(int j =0; j < i; j++)
            {
                if(node.s[j] == '9') continue;
                if(node.s[j] > node.s[i])
                    ivsNum ++;
            }
        }
        if(ivsNum & 1)
            cout<<"unsolvable"<<endl;
        else
            DoubleBFS();
    }
    return 0;
}

逆向BFS+離線打表//不完備

#include <bits/stdc++.h>
using namespace std;
const int N = 512345;
char ss[10];
struct node
{
    char str[10];
    vector<int> res;
    int index,num;
};
vector<int> res[N];
bool vis[N];
int fac[] = {1,1,2,6,24,120,720,5040,40320};
int over;
int ans[N];
int contor(char ss[])
{
    int t,sum;
    int s[10];
    for(int i = 0; i < 9; i++)
    {
        if(ss[i]=='x')
            s[i] = 0;
        else
            s[i]=ss[i]-'0';
    }
    sum = 0;
    for(int i = 0; i < 9;i++)
    {
        t = 0;
        for(int j = i + 1; j < 9; j++)
        {
            if(s[j] < s[i])
                t++;
        }
        sum += t *fac[9-i-1];
    }
    return sum+1;
}
void bfs()
{
   char c;
   queue<node> q;
   over = contor(ss);
   node g,h;
   for(int i = 0; i < 8;i++)
   {
       g.str[i] = i + 1 + '0';
   }
   g.str[8] = 'x';
   g.str[9] = '\0';
   g.res.clear();g.index = 8;g.num = 0;
   int t = contor(g.str);
   vis[t] = true;
   q.push(g);
   while(!q.empty())
   {
       g = q.front(); q.pop();
       int t = contor(g.str);
       res[t] = g.res;
       g.num ++;
       h = g;
       if((h.index+1)%3 != 0)
       {
           swap(h.str[h.index],h.str[h.index+1]);
           h.index ++;
           h.res.push_back(4);
           int t = contor(h.str);
           if(!vis[t])
           {
               vis[t] = true;
               q.push(h);
           }
       }
       h = g;
       if(h.index%3 != 0)
       {
           swap(h.str[h.index],h.str[h.index-1]);
           h.index--;
           h.res.push_back(3);
           int t= contor(h.str);
           if(!vis[t])
           {
               vis[t] = true;
               q.push(h);
           }
       }
       h = g;
       if(h.index < 6)
       {
           swap(h.str[h.index],h.str[h.index+3]);
           h.index += 3;
           h.res.push_back(2);
           int t = contor(h.str);
           if(!vis[t])
           {
               vis[t] = 1;
               q.push(h);
           }
       }
       if(h.index > 2)
       {
           swap(h.str[h.index],h.str[h.index-3]);
           h.index -= 3;
           h.res.push_back(1);
           int t = contor(h.str);
           if(!vis[t])
           {
               vis[t] = 1;
               q.push(h);
           }
       }
   }
}
int main()
{
    int k,t,x,y,z;
    for(int i = 0; i < N; i++) res[i].clear();
    bfs();
    while(scanf("%s",ss)!=EOF)
    {
        memset(vis,false,sizeof vis);
        for(int i = 1; i < 9; i++)
            scanf("%s",ss+i);
            //cout<<ss<<endl;
        t = contor(ss);
      //  for(int i = 1; i<= 46234;i++ )
          //  cout<<res[i].size()<<endl;
        if(res[t].size()!=0 || t == 46234)
        {
            for(int i = res[t].size() - 1; i >= 0; i--)
            {
                if(res[t][i] == 1)      cout<<"d";
                else if(res[t][i] == 2) cout<<"u";
                else if(res[t][i] == 3) cout<<"r";
                else if(res[t][i] == 4) cout<<"l";
            }
        }
        else
            cout<<"unsolvable";
        cout<<endl;
    }
}