poj 1077 Eight(A*)

经典的八数码问题,用来练习各种搜索=_=。这题我用的A*做的,A*的主要思想就是在广搜的时候加了一个估价函数,用来评估此状态距离最终状态的大概距离。这样就可以省下很多状态不用搜索。对于每个状态设置一个函数 h(x),这就是估价函数了(可能名词不太对请见谅),再设置一个函数 g(x), 这存的是初始状态到当前状态所用步数(或距离,视估价函数而定),再设函数 f(x) = g(x) + h(x),我们对每个状态的 f(x)的值进行排序, 然后从当前 f(x) 最小的状态继续搜索,直到搜索到最终状态或者没有后继状态。

上代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define N 10
#define M 500000
using namespace std;

struct sss
{
    int state[N];
    int num, place;
};
priority_queue<sss> q;

int f[M], g[M] = {0}, fa[M] = {0}, move[M] = {0};
sss begin, end;
int step[4][2] = {{-1,0},{0,-1},{0,1},{1,0}};
int color[M] = {0};

bool operator < (sss a, sss b) { return f[a.num] > f[b.num]; }
bool operator == (sss a, sss b) { return a.num == b.num; }

int h(sss a) // h(v)
{
    int z = 0;
    for (int i = 1; i <= 3; ++i)
        for (int j = 1; j <= 3; ++j)
        {
            int x = (i-1)*3+j;
            z += abs(i-(a.state[x]-1)/3) + abs(j-(a.state[x]-(a.state[x]-1)/3*3));
        }
    return z;
}

int jiecheng[N] = {0,1,2,6,24,120,720,5040,40320,362880};
int make_num(sss a) // 康拓展开
{
    int ans = 0; bool xiao[N] = {0};
    for (int i = 1; i <= 9; ++i)
    {
        int count = 0; xiao[a.state[i]] = 1;
        for (int j = 1; j < a.state[i]; ++j)
            if (!xiao[j]) count++;
        ans += count * jiecheng[N-i-1];
    }
    return ans;
}

bool in(sss now, int mo) // 移动可行
{
    int x = (now.place-1)/3+1, y = now.place-(x-1)*3;
    x += step[mo-1][0]; y += step[mo-1][1];
    if (x < 1 || x > 3 || y < 1 || y > 3) return false;
    else return true;
}

void A_star() // A*
{
    q.push(begin); f[begin.num] = h(begin);
    while (!q.empty())
    {
        sss u = q.top(); q.pop();
        if (u == end)
            return;
        for (int i = -3; i <= 3; i+=2)
        {
            if (!in(u,(i+5)/2)) continue;
            sss v; v = u; swap(v.state[u.place+i], v.state[u.place]);
            v.place = u.place + i; v.num = make_num(v);
            if (color[v.num] == 1)
            {
                if (g[u.num] + 1 < g[v.num])
                {
                    f[v.num] = f[v.num] - g[v.num] + g[u.num] + 1;
                    g[v.num] = g[u.num] + 1; move[v.num] = i;
                    q.push(v); fa[v.num] = u.num;
                }
            }
            else if (color[v.num] == 2)
            {
                if (g[u.num] + 1 < g[v.num])
                {
                    f[v.num] = f[v.num] - g[v.num] + g[u.num] + 1;
                    g[v.num] = g[u.num] + 1; fa[v.num] = u.num;
                    q.push(v); color[v.num] = 1; move[v.num] = i;
                }
            }
            else
            {
                g[v.num] = g[u.num] + 1;
                f[v.num] = h(v) + g[v.num];
                color[v.num] = 1; fa[v.num] = u.num;
                q.push(v); move[v.num] = i;
            }
        }
        color[u.num] = 2;
    }
}

char change(int x)
{
    if (x == -1) return ‘l‘;
    else if (x == -3) return ‘u‘;
    else if (x == 1) return ‘r‘;
    else return ‘d‘;
}

void print() // 输出
{
    char s[M], snum = 0;
    int k = fa[end.num];
    s[++snum] = change(move[end.num]);
    while (k != begin.num)
    {
        s[++snum] = change(move[k]);
        k = fa[k];
    }
    for (int i = snum; i > 0; --i)
        printf("%c", s[i]);
    printf("\n");
}

int main()
{
    char s[2];
    for (int i = 1; i <= 9; ++i)
    {
        scanf("%s", s);
        if (s[0] != ‘x‘) begin.state[i] = s[0] - ‘0‘;
        else
        {
            begin.state[i] = 9;
            begin.place = i;
        }
        end.state[i] = i;
    }
    begin.num = make_num(begin);
    end.num = make_num(end);
    A_star();
    print();
}
时间: 2024-08-11 07:48:50

poj 1077 Eight(A*)的相关文章

POJ 3414 Pots(罐子)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

poj 3399 Product(模拟)

# include <stdio.h> # include <string.h> # include <algorithm> using namespace std; int cmp(int x,int y) { return x>y; } int main() { int a[110],a1[110],a2[110],ans[110]; int n,k,k1,k2,i,k3; while(~scanf("%d%d",&n,&k

POJ 1840 Eqs(暴力)

Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 The coefficients are given integers from the interval [-50,50]. It is consider a solution a system (x1, x2, x3, x4, x5) that verifies the equation, xi∈[-50,

POJ 3034 Whac-a-Mole(DP)

题目链接 题意 : 在一个二维直角坐标系中,有n×n个洞,每个洞的坐标为(x,y), 0 ≤ x, y < n,给你一把锤子可以打到地鼠,最开始的时候,你可以把锤子放在任何地方,如果你上一秒在(x1,y1),那下一秒直线移动到的整数点(x2,y2)与这个点的距离小于等于d,并且当锤子移动(x2,y2)这个点时,所有在两点的直线上的整点数都可以打到.例如(0,0)移动到(0,3).如果(0,1),(0,2)有老鼠出现就会被打到.求能够打的最多老鼠. 思路 : Dp[i][j][k]代表点(i,j)

poj 2309 BST(数学题)

BST Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8440   Accepted: 5093 Description Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, 2, 3, .... In a subtree whose root node is X, we c

poj 2485 Highways(最小生成树)

题目链接:http://poj.org/problem?id=2485 Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem. They're plann

poj 1751 Highways (prim )

Highways Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9080   Accepted: 2536   Special Judge Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has a very poor system of public highways. The Flatopian

poj 1861 Network (kruskal)

Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13633   Accepted: 5288   Special Judge Description Andrew is working as system administrator and is planning to establish a new network in his company. There will be N hubs in the c

poj 3399 Product(数学题)

题目链接:http://poj.org/problem?id=3399 Product Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2837   Accepted: 686   Special Judge Description There is an array of N integer numbers in the interval from -30000 to 30000. The task is to sele