uva704 - Colour Hash(彩色转盘)

和大多数ACMer一样,一开始,我习惯性的单项搜索,结果搞了一下午没搞出来,

看了人家的思路,我明白了单向搜16层是多么的可笑啊, 就算把数组开到最大也是不够用的。。。。

正确的做法应该是双向搜索 

这样写了以后,我又呆了,还是不对,我忽略了逆向搜索输出路径是应该也是逆向的,就是说如果原来是逆向3搜过来的,输出是应该是输出3的逆向,就是1。

这是我做过搜索中少有的代码超长的题目,有点力不从心啊,

代码如下:

#include <cstdio>
#include <cstring>
#define MN 100003
using namespace std;
int ok, ans, ans2, head[MN], next[MN], fa[MN], pa[MN], step[MN];
int back_st[MN][24], st[MN][24], sta[24], _aim[24] = {0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0};
int back_head[MN], back_next[MN], back_fa[MN], back_pa[MN];
int is_ok()
{
    for(int i = 0; i < 21; i++) if(sta[i]!=_aim[i]) return 0;
    return 1;
}
int _strcmp(int *a, int *b)
{
    for(int i = 0; i < 21; i++) if(a[i]!=b[i]) return 0;
    return 1;
}
int hash(int cur)
{
    int s = 0;
    for(int i = 0; i < 2l; i++)
        s = (s * 11 + st[cur][i])%MN;
    return s;
}
int is_succeed(int cur)
{
    int h = hash(cur);
    int u = back_head[h];
    while(u)
    {
        if(_strcmp(back_st[u],st[cur])) { ans2 = u; return 1;}
        u = back_next[u];
    }
    return 0;
}
int try_to_insert(int cur)
{
    int h = hash(cur);
    int u = head[h];
    while(u)
    {
        if(_strcmp(st[cur],st[u])) return 0;
        u = next[u];
    }
    next[cur] = head[h];
    head[h] = cur;
    return 1;
}
void bfs(int *A, int state)
{
    int rear = 0, front = 1;
    step[0] = 0;
    for(int i = 0; i < 21; i++) st[0][i] = A[i];
    memset(head,0,sizeof(head));
    memset(next,0,sizeof(next));
    try_to_insert(0);
    while(rear<front)
    {
        if(state>0&&is_succeed(rear)) { ok = 1; ans = rear; break; }
        if(step[rear]>8) break;

        for(int i = 0; i <= 9; i++) st[front][i+2] = st[rear][i];
        st[front][0] = st[rear][10];    st[front][1] = st[rear][11];
        for(int i = 12; i <= 20; i++) st[front][i] = st[rear][i];
        if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 1; fa[front] = rear; front++;}

        for(int i = 9; i <= 18; i++) st[front][i] = st[rear][i+2];
        st[front][19] = st[rear][9];    st[front][20] = st[rear][10];
        for(int i = 0; i <= 8; i++) st[front][i] = st[rear][i];
        if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 2; fa[front] = rear; front++;}

        for(int i = 0; i <= 9; i++) st[front][i] = st[rear][i+2];
        st[front][10] = st[rear][0];    st[front][11] = st[rear][1];
        for(int i = 12; i <= 20; i++) st[front][i] = st[rear][i];
        if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 3; fa[front] = rear; front++;}

        for(int i = 9; i <= 18; i++) st[front][i+2] = st[rear][i];
        st[front][9] = st[rear][19];    st[front][10] = st[rear][20];
        for(int i = 0; i <= 8; i++) st[front][i] = st[rear][i];
        if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 4; fa[front] = rear; front++;}

        rear++;
    }
}
void print_path(int cur)
{
    if(!cur) return;
    print_path(fa[cur]);
    printf("%d",pa[cur]);
}
void back_print_path(int cur)
{
    if(!cur) return;
    if(back_pa[cur]==1)printf("3");
    else if(back_pa[cur]==3)printf("1");
    else if(back_pa[cur]==2)printf("4");
    else if(back_pa[cur]==4)printf("2");
    back_print_path(back_fa[cur]);
}
int main ()
{
    int t;
    scanf("%d",&t);
    bfs(_aim,-1);
    memcpy(back_head,head,sizeof(head));
    memcpy(back_next,next,sizeof(next));
    memcpy(back_fa,fa,sizeof(fa));
    memcpy(back_pa,pa,sizeof(pa));
    memcpy(back_st,st,sizeof(st));
    while(t--)
    {
        for(int i = 0; i < 24; i++)  scanf("%d",&sta[i]);
        if(is_ok()) { puts("PUZZLE ALREADY SOLVED"); continue; }
        ans = ans2 = 0; ok = 0; bfs(sta,1);
        if(ok) { print_path(ans); back_print_path(ans2); printf("\n");}
        else puts("NO SOLUTION WAS FOUND IN 16 STEPS");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值