hdu3567 Eight II 康拓展开+打表+路径回溯+映射

来源:互联网 发布:万方数据库免费入口 编辑:程序博客网 时间:2024/05/17 02:59

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3567
题意:给你一个八数码的起始和终止状态,让你打印路径,要求字典序最小,长度最短,保证输入数据必有解。

思路:2000ms 200组数据,平均10ms一组数据。用A*的话,可能会tle,而且还不能保证字典序最小。所以直接打表,考虑到起点,终点不定,所以需要映射,比如我把起点564178X23映射成123456X87(即12345678X,将7和X交换位置),然后按照这个映射方法,把终点7568X4123映射成5126X3487,那么起点564178X23到终点7568X4123的路径肯定等于123456X87到5126X3487的路径。所以我们可以提前打表,然后通过映射,直接输出表就好了。 但是考虑到X的位置有九种,每次的位置不定,所以我们需要打九次表,然后根据起始状态的X的位置,选择不同的表,输出。
可以先写这道题:http://acm.hdu.edu.cn/showproblem.php?pid=1043
题解:http://blog.csdn.net/acmlzq/article/details/54427716
这里写图片描述
代码:

#include<cstdio>#include<cstring>#include<string>#include<queue>#include<cmath>#include<vector>#include<map>#include<stack>#include<iostream>#include<algorithm>using namespace std;#define ll long long#define inf 0x3f3f3f3f#define scanfprint() freopen("input.txt","r",stdin)#define printfprint() freopen("output.txt","w",stdout)#define mem(a,b) memset(a,b,sizeof(a))const int spot=1000+10;const int edge=100000+10;const int maxn=362880+10;const double pi=acos(-1.0);const int mod=1e9+7;const double ips=0.000001;const int c_n=9;bool c_flag[c_n+10];int c_a[c_n+10],fact[15]= {0,1,1,2,6,24,120,720,5040,40320,362880},m[11][maxn],num=0,casen=0;struct stu1{    int pre;  //上一个    char dir; //方向} memory[11][maxn];  //打表  //第一个下标表示第几个表(几对应的是X所在的位置)struct stu2{    int c_v,num,coor;  //康拓值,打表的下标,表里的下标} s,t;bool flag[maxn];  //int cantor()  //康拓展开 c_a[1]到c_a[n]表示一个全排列,返回的ans表示康拓值(从0开始){    mem(c_flag,0);    int i,j,sum=0,ans=0,k;    for(i=1,k=c_n; i<=c_n; i++,k--)    {        sum=0;        for(j=c_a[i]-1; j>=1; j--)        {            if(!c_flag[j])                sum++;        }        c_flag[c_a[i]]=1,ans+=sum*fact[k];    }    return ans;}void inverse_cantor(int c_m) //康拓逆展开 传入的m是康拓值(从0开始),最终的c_a[1]到c_a[n]是m对应的排列{    mem(c_flag,0);    int i,j,k,sum;    for(i=1,k=c_n; i<=c_n; i++,k--)    {        sum=c_m/fact[k]+1;        for(j=1; j<=c_n; j++)        {            if(!c_flag[j])                sum--;            if(!sum)                break;        }        c_a[i]=j,c_flag[j]=1,c_m%=fact[k];    }}void bfs(int in){    int i,temp;    s.c_v=cantor(),s.num=0,s.coor=in;    flag[s.c_v]=1;    m[in][s.c_v]=0;    queue<stu2>q;    q.push(s);    while(!q.empty())    {dd        s=q.front();        q.pop();        inverse_cantor(s.c_v);        for(i=0; i<4; i++)        {            if(!i)  //下            {                if(s.coor<7)                {                    swap(c_a[s.coor],c_a[s.coor+3]);                    t.c_v=cantor();                    if(!flag[t.c_v])                    {                        t.coor=s.coor+3,t.num=++num;                        memory[in][num].dir='d',memory[in][num].pre=s.num;                        m[in][t.c_v]=num;                        flag[t.c_v]=1;                        q.push(t);                    }                    swap(c_a[s.coor],c_a[s.coor+3]);                }            }            if(i==1)  //左            {                if(s.coor!=1&&s.coor!=4&&s.coor!=7)                {                    swap(c_a[s.coor],c_a[s.coor-1]);                    t.c_v=cantor();                    if(!flag[t.c_v])                    {                        t.coor=s.coor-1,t.num=++num;                        memory[in][num].dir='l',memory[in][num].pre=s.num;                        m[in][t.c_v]=num;                        flag[t.c_v]=1;                        q.push(t);                    }                    swap(c_a[s.coor],c_a[s.coor-1]);                }            }            if(i==2) //右            {                if(s.coor!=3&&s.coor!=6&&s.coor!=9)                {                    swap(c_a[s.coor],c_a[s.coor+1]);                    t.c_v=cantor();                    if(!flag[t.c_v])                    {                        t.coor=s.coor+1,t.num=++num;                        memory[in][num].dir='r',memory[in][num].pre=s.num;                        m[in][t.c_v]=num;                        flag[t.c_v]=1;                        q.push(t);                    }                    swap(c_a[s.coor],c_a[s.coor+1]);                }            }            if(i==3)//上            {                if(s.coor>3)                {                    swap(c_a[s.coor],c_a[s.coor-3]);                    t.c_v=cantor();                    if(!flag[t.c_v])                    {                        t.coor=s.coor-3,t.num=++num;                        memory[in][num].dir='u',memory[in][num].pre=s.num;                        m[in][t.c_v]=num;                        flag[t.c_v]=1;                        q.push(t);                    }                    swap(c_a[s.coor],c_a[s.coor-3]);                }            }        }    }}void print(int in,int n,int step){    if(!n)    {        printf("Case %d: %d\n",++casen,step);        return ;    }    print(in,memory[in][n].pre,step+1);    printf("%c",memory[in][n].dir);}void init()  //打九张表{    int i,j,temp;    for(i=1; i<=9; i++)    {        mem(flag,0),num=0;        for(j=1; j<=9; j++)            c_a[j]=j;        swap(c_a[i],c_a[9]);        bfs(i);    }}void solve()  //先映射{    int a1[15],a2[15],temp1[15],temp2[15],i,j,sub;    char s1[15],s2[15];    scanf("%s%s",s1+1,s2+1);    for(i=1; i<=9; i++)    {        if(s1[i]=='X')            sub=i,a1[i]=9;        else            a1[i]=s1[i]-'0';        temp1[i]=i;        a2[i]=s2[i]=='X'?9:s2[i]-'0';    }    swap(temp1[sub],temp1[9]);    for(i=1; i<=9; i++)        temp2[a1[i]]=temp1[i];    for(i=1; i<=9; i++)        c_a[i]=temp2[a2[i]];    int ans=cantor();    print(sub,m[sub][ans],0);    puts("");}int main(){    init();    int nn;    scanf("%d",&nn);    while(nn--)    {        solve();    }}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 付款付错了怎么办 手机淘宝太卡怎么办 卖家不同意退货怎么办 游戏退出无响应怎么办 手机淘宝购物车打不开怎么办 淘宝店铺没有访客怎么办 淘宝店铺0流量怎么办 微信经常封号怎么办 网上拍卖堂违约怎么办 dnf4开组队制裁怎么办 红酒木塞丢了怎么办 红酒塞子进去了怎么办 淘金币即将过期怎么办 淘金币过期怎么办2018 换详情排名下降怎么办 长城宽带不用了怎么办 快递到了想退货怎么办 淘宝退货商家拒收怎么办 淘宝运费险失败怎么办 忘记购买运费险怎么办 咸鱼买家申请退款怎么办 熟猪肉有点变味怎么办 和领导意见不一致怎么办 骑手提前点送达怎么办 ubuntu安装报错怎么办 液相色谱两峰分不开怎么办 液相色谱柱老堵怎么办? 没有装usb驱动怎么办 ipad速度越来越慢怎么办 美萍管理软件打不开怎么办 小米4开机黑屏怎么办 小米电脑死机了怎么办 小米8手机死机怎么办 oppa7开不了机怎么办 oppo手机wlan打不开怎么办 三星s6进水黑屏怎么办 银行卡不支持快捷支付怎么办 路由器忘记管理员密码怎么办 云付没有推荐人怎么办 牛呗审核不通过怎么办 华硕笔记本很卡怎么办