704 - Colour Hash

描述:采用双广搜完成,因为单广搜层数太多,不但超时(结果根本出不来),而且还超内存(开不下这么大的数组),双广搜分为两部分,每部分的层数都为8层,分别是从开始的转轮和最终的转轮开始广搜,遇到重合了就可以输出路径,如果不重合,顶多两部分全都搜完,由于目标转轮是确定的,所以第一次的从目标转轮进行的广搜可以存储下来,以后只需要从开始的转轮广搜就可以了,这样可以节省时间。
#include <stdio.h>
#include <string.h>
#define MAX 200000
#define HASHSIZE 10000003
struct way
{
    int step;
    int l;
    int len;
    int s[21];
};
int head[2][HASHSIZE], next[2][MAX];
int a[24];
int front, rear,mid, flag;
int target[21] = {0, 3, 4, 3, 0, 5, 6, 5, 0, 1, 2, 1, 0, 7, 8, 7, 0, 9, 10, 9, 0};
way v[MAX];
int hash(int *p)
{
    int c = 0;
    for (int i = 0; i < 21; i++)
        c = (c * 10 + p[i]) % HASHSIZE;
    return c;
}
int insert(int t, int cur)
{
    int h = hash(v[t].s);
    int u = head[cur][h];
    while(u != -1)
    {
        if (memcmp(v[t].s, v[u].s, sizeof(v[t].s)) == 0)   return 0;
        u = next[cur][u];
    }
    next[cur][t] = head[cur][h];
    head[cur][h] = t;
    return 1;
}
int search(int pos)
{
    int h = hash(v[pos].s);
    int u = head[1][h];
    while (u != -1)
    {
        if (memcmp(v[u].s, v[pos].s, sizeof(v[pos].s)) == 0)  return u;
        u = next[1][u];
    }
    return -1;
}
void show1(int pos)
{
    if (v[pos].l == -1) return;
    show1(v[pos].l);
    printf("%d", v[pos].len);
}
void show2(int pos)
{
    if (v[pos].l == -1) return;
    if(v[pos].len>2) printf("%d", v[pos].len-2 );
    else printf("%d", v[pos].len +2);
    show2(v[pos].l);
}
void bfs(int cur)
{
    way tmpway, newway;
    memcpy(v[front].s, a, sizeof(v[front].s));
    v[front].l = -1;
    v[front].step = v[front].len = 0;
    insert(front, cur);
    while (front < rear)
    {
        tmpway = v[front];
        if (!cur &&  (mid = search(front)) != -1)
        {
            show1(front);
            show2(mid);
            printf("\n");
            flag=1;
            return;
        }
        if (tmpway.step <8) for(int i=1; i<=4; i++)
            {
                newway = tmpway;
                newway.l = front;
                newway.step++;
                newway.len = i;
                int temp1, temp2;
                if(i==1)
                {
                    temp1 = newway.s[10];
                    temp2 = newway.s[11];
                    for (int i = 9; i >= 0; i--) newway.s[i + 2] = newway.s[i];
                    newway.s[0] = temp1;
                    newway.s[1] = temp2;
                }
                else if(i==2)
                {
                    temp1 = newway.s[9];
                    temp2 = newway.s[10];
                    for (int i = 9; i < 19; i++)  newway.s[i] = newway.s[i + 2];
                    newway.s[20] = temp2;
                    newway.s[19] = temp1;
                }
                else if(i==3)
                {
                    temp1 = newway.s[0];
                    temp2 = newway.s[1];
                    for (int i = 2; i < 12; i++)   newway.s[i - 2] = newway.s[i];
                    newway.s[10] = temp1;
                    newway.s[11] = temp2;
                }
                else
                {
                    temp1 = newway.s[19];
                    temp2 = newway.s[20];
                    for (int i = 18; i >= 9; i--)  newway.s[i + 2] = newway.s[i];
                    newway.s[9] = temp1;
                    newway.s[10] = temp2;
                }
                v[rear] = newway;
                if (insert(rear, cur)) rear++;
            }
        front++;
    }
}
int main()
{
    int n;
#ifndef ONLINE_JUDGE
    freopen("a.txt", "r", stdin);
#endif
    scanf("%d", &n);
    memset(head, -1, sizeof(head));
    memset(next,0,sizeof(next));
    front =0;
    rear = 1;
    memcpy(a, target, sizeof(target));
    bfs(1);
    int score1=front,score2=rear;
    while (n--)
    {
        for (int i = 0; i < 24; i++)  scanf("%d", &a[i]);
        memset(head[0], -1, sizeof(head[0]));
        memset(next[0],0,sizeof(next[0]));
        if(memcmp(a,target,sizeof(target))==0) printf("PUZZLE ALREADY SOLVED\n");
        else
        {
            front=score1;
            rear=score2+1;
            flag=0;
            bfs(0);
            if(!flag) printf("NO SOLUTION WAS FOUND IN 16 STEPS\n");
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值