UVA 1533 Moving Pegs(bfs+hash)
제목:
점프 바둑 하나에 빈자리를 주다.최소 걸음 수를 구하고 사전 순서가 가장 작아서 마지막 바둑판에 깃발 하나만 남기고 처음의 빈자리에 놓인다.
아이디어:
BFS+hash가 무게를 판정했는데 이 문제의 사고방식은 비교적 좋았다. 그러나 내가 보기에 네트워크 위의 코드는 모두 타표+bfs이다. 나는 상태를 2차원 그룹으로 직접 전환하고 6개 방향에 대해 bfs를 한다.
AC 코드
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int dx[] = {-1,-1, 0, 0, 1, 1};
const int dy[] = {-1, 0,-1, 1, 0, 1};
const int N = 1<<16;
struct State {
int grid[5][5], num; //the last pos and the step
vector< pair<int,int> > path; //first from second to
//init
State() {
memset(grid, false, sizeof(grid));
num = 0;
path.clear();
}
//create function
State(int _grid[][5], int _num) {
memcpy(grid, _grid, sizeof(grid));
num = _num;
}
//hash
int Hash() {
int sum = 0, cnt = 1;
for(int i = 0; i < 5; i++)
for(int j = 0; j <= i; j++)
sum |= grid[i][j] << cnt++;
return sum;
}
};
vector< pair<int,int> > ans;
int state[5][5], vis[N];
int empty;
void init() {
memset(vis, false, sizeof(vis));
memset(state, -1, sizeof(state));
int cnt = 1;
for(int i = 0; i < 5; i++) {
for(int j = 0; j <= i; j++) {
if(empty != cnt++) state[i][j] = 1;
else state[i][j] = 0;
}
}
}
int trans(int x, int y) {
return x*(x+1)/2 + (y+1);
}
bool check(int grid[][5]) {
int pos = 0;
for(int i = 0; i < 5; i++) {
for(int j = 0; j <= i; j++) {
if(grid[i][j]) pos = trans(i, j);
}
}
return pos == empty;
}
bool overBound(int x, int y) {
if(x < 0 || x >= 5 || y < 0 || y >= 5)
return true;
return false;
}
bool bfs() {
//init
queue<State> que;
que.push(State(state, 14));
State front = que.front(), tmpState;
vis[front.Hash()] = true;
int nx, ny, len;
while(!que.empty()) {
front = que.front(); que.pop();
if(front.num == 1 && check(front.grid)) {
ans = front.path; return true;
}
for(int x = 0; x < 5; x++) {
for(int y = 0; y <= x; y++) { //num
if(front.grid[x][y] == 0) continue;
for(int i = 0; i < 6; i++) { //direction
nx = x + dx[i], ny = y + dy[i];
if(!overBound(nx, ny)) {
len = 1;
tmpState = front;
while(tmpState.grid[nx][ny] == 1 && !overBound(nx, ny)) {
tmpState.grid[nx][ny] = 0;
len++;
nx += dx[i], ny += dy[i];
}
}
if(tmpState.grid[nx][ny] == -1 || overBound(nx,ny) || len < 2) continue;
tmpState.grid[nx][ny] = 1; tmpState.grid[x][y] = 0;
tmpState.num -= (len-1);
tmpState.path.push_back(make_pair(trans(x,y), trans(nx,ny)));
int tmp = tmpState.Hash();
if(!vis[tmp]) {
vis[tmp] = true;
que.push(tmpState);
}
}
}
}
}
return false;
}
int main() {
// freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &empty);
init();
if(!bfs()) {
printf("IMPOSSIBLE
");
}else {
printf("%d
", ans.size());
printf("%d %d", ans[0].first, ans[0].second);
for(int i = 1; i < ans.size(); i++)
printf(" %d %d", ans[i].first, ans[i].second);
puts("");
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
UVA - 10986 Sending email(Dijkstra 인접 테이블 + 우선 순위 대기열 최적화)제목 대의: s점에서 t점까지의 최소 거리를 구하는 그림을 주세요. 확인: 적나라한 최단길이지만 n이 너무 크면 인접 행렬을 사용할 수 없기 때문에 Dijkstra에 대한 인접표 + 우선 대기열 최적화가 필요합니다....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.