记忆化搜索( 石油大学组队赛A: Rush Hour Puzzle)

在这里插入图片描述
题意:如图,把一号车从出口(3,6)弄出去,最少多少步,(10步以上输出-1)
题解:没啥知识含量,就硬模拟,记录压缩状态dp[sta],因为每个车都只会在自己所在的列、行移动,所以压缩是只记录一维就行。每个坐标最多6种情况(其实可以在针对车进行压缩,每个车都是4、5个情况。但是空间已经够了)。所以状态为 6 n 6^n 6n种,n为车的数量。然后就是模拟转移+记忆化搜索。
下面是ac代码:

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;
const int N = 12;
const int inf = 0x3f3f3f3f;
struct Node
{
    int x, y;
    int t, d;
} s[N];
int mp[N][N], su[N][N];
int dp[61000010];
int mx = 0;
int ha(Node * s)
{
    int ans = 0;
    for (int i = 1; i <= mx; i++)
    {
        int c;
        if (s[i].d == 0)
            c = s[i].y;
        else
            c = s[i].x;
        ans = ans * 6 + c - 1;
    }
    return ans;
}
void rha(int h, Node * je, int  vis[][10])
{
    for (int i = 0;i<= 6; i++)
        for (int j = 0; j<= 6; j++)
            vis[i][j] = 0;
    int cnt = mx;
    while(cnt)
    {
        int g = h % 6;
        je[cnt] = s[cnt];
        if (je[cnt].d == 0)
        {
            je[cnt].y = g + 1;
        }
        else
        {
            je[cnt].x = g + 1;
        }
        vis[je[cnt].x][je[cnt].y] = cnt;
        if (je[cnt].d == 1)
        {
            vis[je[cnt].x-1][je[cnt].y] = cnt;
            if (je[cnt].t == 3)
                vis[je[cnt].x-2][je[cnt].y] = cnt;
        }
        else
        {
            vis[je[cnt].x][je[cnt].y-1] = cnt;
            if (je[cnt].t == 3)
                vis[je[cnt].x][je[cnt].y-2] = cnt;
        }
        h /= 6;
        cnt--;
    }
}
bool che(int x, int y, int vis[][10])
{
    return x > 0 && x <= 6 && y > 0 && y <= 6 && vis[x][y] == 0;
}
void tran(Node * g, int i, int flag)
{
    if (g[i].d == 0) g[i].y+=flag;
    else g[i].x+=flag;
}
void print(int  vis[][10])
{
    cout << "-----------------" << endl;
    for (int i = 1; i <= 6; i++)
    {
        for (int j = 1; j <= 6; j++)
            cout <<vis[i][j] << " ";
        cout << endl;
    }
}
int ans = 0x3f3f3f3f;
void dfs(int sta, int dep)
{
    if (dp[sta]<=dep) return;
    dp[sta] = dep;
    if (dep + s[1].d - 1 > 10) return;
    Node g[10];
    int vis[10][10];
    rha(sta, g, vis);
    //print(vis);
 
 
 
    //system("pause");
    if ( ( ( g[1].x == 3 && g[1].y == 6)  ) )
    {
        //cout << "sd" << endl;
        if(g[1].d == 0)
            ans = min(ans, dep);
        return;
    }
    for (int i = 1; i <= mx; i++)
    {
        if (g[i].d == 0)
        {
            if ( che(g[i].x, g[i].y - g[i].t , vis) )
            {
                tran(g, i, -1);
                dfs(ha(g), dep+1);
                tran(g, i, 1);
            }
            if ( che(g[i].x, g[i].y+1, vis) )
            {
                tran(g, i, 1);
                dfs(ha(g), dep+1);
                tran(g, i, -1);
            }
        }
        else
        {
            if ( che(g[i].x-g[i].t, g[i].y, vis) )
            {
                tran(g, i, -1);
                dfs(ha(g), dep+1);
                tran(g, i, 1);
            }
            if ( che(g[i].x+1, g[i].y, vis) )
            {
                tran(g, i, 1);
                dfs(ha(g), dep+1);
                tran(g, i, -1);
            }
        }
    }
}
int main()
{
    //memset(dp,0x3f,sizeof(dp));
 
    for (int i = 1; i <= 6; i++)
    {
        for (int j = 1; j <= 6; j++)
        {
            scanf("%d", &su[i][j]);
            if (su[i][j] == 0) continue;
            s[su[i][j]].x = i, s[su[i][j]].y = j,
            mp[i][j] = 1;
            if (su[i][j] == su[i][j-1])
                s[su[i][j]].d = 0, mp[i][j] += mp[i][j-1];
            if (su[i][j] == su[i-1][j])
                s[su[i][j]].d = 1, mp[i][j] += mp[i-1][j];
            s[su[i][j]].t = mp[i][j];
            mx = max(mx, su[i][j]);
        }
    }
    //for(int i=0;i<=mx;i++)
    //    cout<<s[i].t<<endl;
    //for (int i = 1; i <= mx; i++)
    //    cout << s[i].d << endl;
    int g = ha(s);
    memset(dp, 0x3f, sizeof(dp));
    dfs(g, 1);
    int gg = ans + s[1].t-1;
    printf("%d\n", gg > 10 ? -1 : gg);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值