HDU356 Eight II(康拓展开+预处理)

来源:互联网 发布:app软件大全 编辑:程序博客网 时间:2024/04/30 13:43

双向BFS会TLE, T_T , 但是离线就不会了

虽然TLE了, 还是贴出来留个纪念吧

#include <iostream>
#include <stdlib.h>
#include <queue>
#include <string.h>
#include <algorithm>
#include <stdio.h>


using namespace std;
const int MAXN=1000000;//最多是9!/2
struct node
{
    bool type;
    int num[10];
    int sta;
    int loc;
};
int move[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
char index[5] = "rldu";
char index2[5] = "lrud";
int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//康拖展开判重
//         0!1!2!3! 4! 5!  6!  7!   8!    9!
bool vis1[MAXN], vis2[MAXN];//标记
string path1[MAXN];
string path2[MAXN];
int aim;
int cantor(int s[])//康拖展开求该序列的hash值
{
    int sum=0;
    for(int i=0;i<9;i++)
    {
        int num=0;
        for(int j=i+1;j<9;j++)
          if(s[j]<s[i])num++;
        sum+=(num*fac[9-i-1]);
    }
    return sum+1;
}


bool check( string str1, string str2)
{
    string a, b;
    a = str1, b = str2;
    if(a > b)
     return 1;
    return 0;
}
void bfs( node a, node b)
{
     if(a.sta == b.sta)
     {
         cout<<path1[a.sta]<<endl;
         return ;
     }
     queue<node> que;
     while(!que.empty()) que.pop();


     vis1[a.sta] = vis2[b.sta] = 1;
     path1[a.sta] = path2[b.sta] = "";
     que.push(a);
     que.push(b);
     node tem, now;


     while(!que.empty())
     {
          now = que.front();
          que.pop();


         int x = now.loc/3;
         int y = now.loc%3;


         for( int i = 0; i < 4; i++ )
         {
             int tx = x + move[i][0];
             int ty = y + move[i][1];
             if(ty < 0 || ty > 2 || tx < 0 || tx > 2)  continue;


             tem = now;
             tem.loc = tx*3 + ty;
             tem.num[now.loc] = tem.num[tem.loc];
             tem.num[tem.loc] = 0;
             tem.sta = cantor(tem.num);


             if(tem.type == 0 && !vis1[tem.sta])
               {
                   vis1[tem.sta] = 1;
                   path1[tem.sta] = path1[now.sta] + index[i];
                   que.push(tem);
               }
             if(tem.type == 1)
             {
                 if(!vis2[tem.sta])
                {
                    vis2[tem.sta] = 1;
                    path2[tem.sta] = path2[now.sta] + index2[i];
                    for( int i = 0; i < 9; i++)
                    que.push(tem);
                }
                else if(check(path2[tem.sta], path2[now.sta] + index2[i]))
                    path2[tem.sta] =  path2[now.sta] + index2[i];




             }
              if((tem.type == 0 && vis2[tem.sta]) || (tem.type == 1 && vis1[tem.sta]))
             {
                cout<<path1[tem.sta].size()+path2[tem.sta].size()<<endl;
                reverse(path2[tem.sta].begin(),path2[tem.sta].end());
                cout<<path1[tem.sta]<<path2[tem.sta]<<endl;
                return ;
             }
         }
     }
}
void input( node &a)
{
    char s;
    for(int i = 0; i < 9; i++)
     {
         cin>>s;
         if(s == 'X')
           {
               a.num[i] = 0;
               a.loc = i;
           }
         else
          a.num[i] = s - '0';
     }


}








int main()
{
    node a,b;
    int t,ca = 1;
    cin>>t;
    while(ca<=t)
    {
        memset(vis1, 0, sizeof(vis1));
        memset(vis2, 0, sizeof(vis2));
        input(a);
        input(b);
        a.sta = cantor(a.num);
        b.sta = cantor(b.num);
        a.type = 0;
        b.type = 1;
        printf("Case %d: ",ca++);
        bfs(a, b);
    }
}



正确答案

#include <iostream>

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
using namespace std;


struct node
{
    int x,y;
    char map[5][5];
    node() {}
    node(char *s)
    {
        int i,j;
        int xx = 0,yy = 0;
        for(i = 0; i<strlen(s); i++)
        {
            map[xx][yy] = s[i];
            if(s[i] == 'X')
            {
                x = xx;
                y = yy;
            }
            yy++;
            if(yy == 3)
            {
                xx++;
                yy = 0;
            }
        }
    }
};


node s;
char str[20];
int num[20],hash[10];
bool vis[500000];
int pre[10][500000],ans[10][500000];
int to[4][2] = {1,0,0,-1,0,1,-1,0};
char way[10] = "dlru";


int solve(node a)//康拓
{
    int i,j,k,cnt,ans = 0;
    int b[20];
    for(i = 0; i<3; i++)
    {
        for(j = 0; j<3; j++)
        {
            b[3*i+j] = a.map[i][j];
            cnt = 0;
            for(k = 3*i+j-1; k>=0; k--)
            {
                if(b[k]>b[3*i+j])
                    cnt++;
            }
            ans+=hash[3*i+j]*cnt;
        }
    }
    return ans;
}


void bfs(int p)
{
    memset(pre[p],-1,sizeof(pre[p]));
    memset(vis,false,sizeof(vis));
    node a,next;
    queue<node> Q;
    Q.push(s);
    vis[solve(s)] = true;
    while(!Q.empty())
    {
        a = Q.front();
        Q.pop();
        int sa = solve(a);
        for(int i = 0; i<4; i++)
        {
            next = a;
            next.x+=to[i][0];
            next.y+=to[i][1];
            if(next.x<0 || next.x>2 || next.y<0 || next.y>2)
                continue;
            next.map[a.x][a.y] = next.map[next.x][next.y];
            next.map[next.x][next.y] = 'X';
            int sb = solve(next);
            if(vis[sb])
                continue;
            vis[sb] = true;
            pre[p][sb] = sa;
            ans[p][sb] = way[i];
            Q.push(next);
        }
    }
}


int main()
{
    int t,i,j,k,cas = 1;
    hash[0] = 1;
    for(i = 1; i<10; i++)
        hash[i] = hash[i-1]*i;


    s = node("X12345678");
    bfs(0);
    s = node("1X2345678");
    bfs(1);
    s = node("12X345678");
    bfs(2);
    s = node("123X45678");
    bfs(3);
    s = node("1234X5678");
    bfs(4);
    s = node("12345X678");
    bfs(5);
    s = node("123456X78");
    bfs(6);
    s = node("1234567X8");
    bfs(7);
    s = node("12345678X");
    bfs(8);


    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",str);
        int p;
        for(i = 0,j = 0; i<9; i++)//保存位置,因为前面预处理的都是位置
        {
            if(str[i]=='X') p = i;
            else
                num[str[i]-'0'] = j++;
        }
        scanf("%s",str);
        for(i = 0; i<9; i++)//求出目标状态每个数在原状态的位置
        {
            if(str[i]=='X')
                continue;
            str[i] = num[str[i]-'0']+'1';
        }
        s = node(str);//由目标态逆推到初始态
        int sum = solve(s);
        string ss="";
        while(sum!=-1)
        {
            ss+=ans[p][sum];
            sum = pre[p][sum];
        }
        printf("Case %d: %d\n",cas++,ss.size()-1);
        for(i = ss.size()-2; i>=0; i--)//由于方案是逆推,输出也要逆推
            printf("%c",ss[i]);
        printf("\n");
    }


    return 0;
}

0 0