您的位置:首页 > 其它

POJ 1077 解题报告

2014-12-13 05:30 253 查看
这道题我是用bfs+hash做的,最好的方法应该是双向bfs或是A*。虽然这学期刚学的AI,但是偷懒,就这样过了吧。

POJ不支持unordered_map,所以得自己写hash,好在比较简单。由于棋盘是9位的(算上空白位置,那一位我用0填充的),所以每个棋盘(即状态值)可以用一个int表示。每个状态需要记录状态值,空白位置,前一个状态值,及怎么从前一个状态值move过来的。这里用的是hash来从状态值获取这些信息。我取的是状态值的前6位作为hash值,建立了一个链式哈希,即将映射到同一个哈希值的所有信息都用一个链表串起来。

另外,这道题是special judge,意思是说答案有多个,不唯一。我的答案就和标准答案不一样,但都是对的。

1077Accepted11696K688MSG++3169B
/*
ID: thestor1
LANG: C++
TASK: poj1077
*/
#include <iostream>
#include <fstream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <cassert>

using namespace std;

class State
{
public:
int value, zero, prev, move;
State *next;

State() {}
State(int value, int zero, int prev, int move) : value(value), zero(zero), prev(prev), move(move) {}
};

const int MAXN = 1000000;
State* Hash[MAXN] = {NULL};

void insert(int value, int zero, int prev, int move)
{
int key = value % MAXN;
State *newstate = new State(value, zero, prev, move);
newstate->next = Hash[key];
Hash[key] = newstate;
}

State* find(int value)
{
int key = value % MAXN;
State *state = Hash[key];
while (state != NULL && state->value != value)
{
state = state->next;
}
return state;
}

// right, left, up, down
int dr[4] = {0, 0, -1, 1}, dc[4] = {1, -1, 0, 0};

int getinitialstate(string &state)
{
int num = 0;
int k = 0, z = -1;
for (int i = 0; i < state.size(); ++i)
{
if ('1' <= state[i] && state[i] <= '9')
{
num = num * 10 + state[i] - '0';
if (z < 0)
{
k++;
}
}
else if (state[i] == 'x')
{
num = num * 10;
z = k;
}
}
insert(num, z, num, -1);
return num;
}

int next(const int state, int z, int r, int c, int d)
{
r += dr[d], c += dc[d];

if (0 <= r && r <= 2 && 0 <= c && c <= 2)
{
int nz = r * 3 + c;
int base = pow((double)10, 8 - nz);
int digit = (state / base) % 10;
int newbase = pow((double)10, 8 - z);
int num = state - digit * base + digit * newbase;
if (find(num) != NULL)
{
return -1;
}
insert(num, nz, state, d);
return num;
}
else
{
// invalid move
return -1;
}
}

int main()
{
const int finalstate = 123456780;

string line;
getline(cin, line);

int initialstate = getinitialstate(line);
// cout << "[debug]initialstate:" << initialstate << endl;

queue<int> que;
que.push(initialstate);

char directions[4] = {'r', 'l', 'u', 'd'};

bool found = false;
int state, newstate;
while (!que.empty())
{
state = que.front();
que.pop();
if (state == finalstate)
{
found = true;
break;
}

State *s = find(state);
assert (s != NULL);

int z = s->zero;
int r = z / 3, c = z % 3;
for (int d = 0; d < 4; ++d)
{
newstate = next(state, z, r, c, d);
// cout << "next " << directions[d] << ", " << newstate << endl;
if (newstate > 0)
{
que.push(newstate);
}
}
}

if (found)
{
stack<char> st;
state = finalstate;
State *s;
while (state != initialstate)
{
s = find(state);
// cout << "[found]state:" << state << ", prev:" << prev[state] << ", move:" << move[state] << endl;
st.push(directions[s->move]);
state = s->prev;
}
while (!st.empty())
{
cout << st.top();
st.pop();
}
cout << endl;
}
else
{
cout << "unsolvable" << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: