bfs UVA 1063 Marble Game
2014-02-07 17:32
204 查看
A Marble Game is played with M marbles on a square board. The board is divided into
N×N unit squares, and
M of those unit squares contain holes. Marbles and holes are numbered from 1 to
M . The goal of the Marble game is to roll each marble into the hole that has the same number.
A game board may contain walls. Each wall is one unit long and stands between two adjacent unit squares. Two squares are considered adjacent if and only if they share a side.
At the beginning of the game, all marbles are placed on the board, each in a different square. A ``move" consists of slightly lifting a side of the game board. Then all marbles on the board roll downward toward the opposite side, each one rolling until it
meets a wall or drops into an empty hole, or until the next square is already occupied by another marble. Marbles roll subject to the following restrictions:
Marbles cannot jump over walls, other marbles, or empty holes.
Marbles cannot leave the board. (The edge of the board is a wall.)
A unit square can contain at most a single marble at any one time.
When a marble moves into a square with a hole, the marble drops into that hole. The hole is then filled, and other marbles can subsequently roll over the hole. A marble in a hole can never leave that hole.
The game is over when each marble has dropped into a hole with the corresponding number.
The figure below illustrates a solution for a game played on a
4×4 board with three blue marbles, three holes and a wall. The solution has five moves: lift the east side, lift the north side, lift the south side, lift the west side, lift the north side.
Your program should determine the fewest number of moves to drop all the marbles into the correct holes -- if such a move sequence is possible.
Input
The input file contains several test cases. The first line of each test case contains three numbers: the size
N (2
N
4)
of the board, the number M
(M > 0) of marbles, and the number W of walls. Each of the following
2M lines contains two integers. The first integer is a row location and the second is a column location. The first
M of those lines represent the locations of the marbles, where marble#1 is on the first line, marble#2 on the second, and so on. The last
M of those lines represent the locations of the holes, with the location of hole#1 coming first, hole#2 coming second, and so on. Finally, the next
W lines represent the wall locations. Each of those lines contains four integers: the first pair are the row and column of the square on one side of the wall and the second pair are the row and column of the square on the
other side of the wall. Rows and columns are numbered 0..N - 1 .
The input file ends with a line containing three zeroes.
Output
For each test case, print the case number (beginning with 1) and the minimal number of moves to win the game. If the game cannot be won, print the word ``impossible". Put a blank line after each test case. Use the format of the sample output below.
Sample Input
Sample Output
题意:每一次能将所有的球往上下左右一个方向移动到不能移动。如果球进了洞,其他球可以从这个洞上面通过。问最少步数。
思路:直接宽搜,不过写的比较复杂啊。。。判重和状态转移都很麻烦。。比赛遇到这样的题的话,对我来说简直就是灾难,如果能过,倒还好,如果写出来了但是不过就直接崩溃了。这里面move不会因为单复数而WA的,所以不用担心。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define LL long long
const int maxs = 100007;
int n , m , w;
struct Point
{
Point(int rr,int cc , int v) : val(v) , r(rr) , c(cc) { }
bool operator<(const Point & p) const { return val < p.val; }
bool operator == (const Point & p) const { return r==p.r && c==p.c; }
int val;
int r;
int c;
};
inline bool cmp0(const Point&p1,const Point&p2) { return p1.r < p2.r; }
inline bool cmp1(const Point&p1,const Point&p2) {return p1.c > p2.c; }
inline bool cmp2(const Point&p1,const Point&p2) {return p1.r > p2.r; }
inline bool cmp3(const Point&p1,const Point&p2) {return p1.c < p2.c; }
int hole[7][7];
const int Move[2][4] = { {-1,0,1,0},{0,1,0,-1} };
bool cango[7][7][4];
struct State
{
State cpy() const {
State s;
s.ball = ball;
s.g = g;
memcpy(s.ocp,ocp,sizeof(s.ocp));
return s;
}
bool equals(State & st) const {
State tmp = *this;
sort(tmp.ball.begin(),tmp.ball.end());
sort(st.ball.begin(),st.ball.end());
for (int i = 0 ; i < tmp.ball.size() ; ++i)
{
if (tmp.ball[i]==st.ball[i]) continue;
return false;
}
return true;
}
vector<Point> ball;
bool ocp[7][7];
int g;
}start;
vector<State> hsh[maxs];
int key(const State & st)
{
LL ret = 0;
for (int i = 0 ; i < st.ball.size() ; ++i)
ret += 1313*(((LL)st.ball[i].r*1313+st.ball[i].c*13)*st.ball[i].val)%maxs;
return ret % maxs;
}
bool vis(State & st)
{
int k = key(st);
for (int i = 0 ; i < hsh[k].size() ; ++i)
if (st.equals(hsh[k][i])) return true;
return false;
}
void insert(const State & st)
{
int k = key(st);
hsh[k].push_back(st);
}
void input()
{
for (int i = 0 ; i < maxs ; ++i) hsh[i].clear();
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < n ; ++j)
for (int k = 0 ; k < 4 ; ++k)
cango[i][j][k] = true;
for (int i = 0 ; i < n ; ++i) cango[i][0][3] = false;
for (int i = 0 ; i < n ; ++i) cango[0][i][0] = false;
for (int i = 0 ; i < n ; ++i) cango[i][n-1][1] = false;
for (int i = 0 ; i < n ; ++i) cango[n-1][i][2] = false;
start.ball.clear();
memset(start.ocp,false,sizeof(start.ocp));
start.g = 0;
memset(hole,-1,sizeof(hole));
for (int i = 0 ; i < m ; ++i) {
int r , c;
scanf("%d%d",&r,&c);
start.ball.push_back(Point(r,c,i+1));
start.ocp[r][c] = true;
}
for (int i = 0 ; i < m ; ++i) {
int r , c;
scanf("%d%d",&r,&c);
start.ocp[r][c] = true;
hole[r][c] = i+1;
}
for (int i = 0 ; i < w ; ++i) {
int r1 , c1 , r2,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if (r1+1==r2) { cango[r1][c1][2] = cango[r2][c2][0] = false; }
if (r1-1==r2) { cango[r1][c1][0] = cango[r2][c2][2] = false; }
if (c1+1==c2) { cango[r1][c1][1] = cango[r2][c2][3] = false; }
if (c1-1==c2) { cango[r1][c1][3] = cango[r2][c2][1] = false; }
}
}
void expand(State & st,int k,queue<State>&q)
{
if (k==0) sort(st.ball.begin(),st.ball.end(),cmp0);
else if (k==1) sort(st.ball.begin(),st.ball.end(),cmp1);
else if (k==2) sort(st.ball.begin(),st.ball.end(),cmp2);
else sort(st.ball.begin(),st.ball.end(),cmp3);
++st.g;
for (int i = 0 ; i < st.ball.size() ; ++i) {
Point & p = st.ball[i];
int r = p.r , c = p.c;
if (hole[r][c]==p.val) continue;
int rr = r , cc = c;
while (true) {
if (!cango[rr][cc][k]) break;
rr += Move[0][k];
cc += Move[1][k];
if (st.ocp[rr][cc]) {
if (hole[rr][cc]!=-1) {
if (hole[rr][cc]!=p.val) return;
else break;
}
rr -= Move[0][k];
cc -= Move[1][k];
break;
}
}
st.ocp[r][c] = false;
if (hole[rr][cc]!=p.val) st.ocp[rr][cc] = true;
else st.ocp[rr][cc] = false;
p.r = rr , p.c = cc;
}
if (vis(st)) return;
insert(st);
q.push(st);
}
bool finish(const State & st)
{
for (int i = 0 ; i < st.ball.size() ; ++i) {
const Point & p = st.ball[i];
if (hole[p.r][p.c]!=p.val) return false;
}
return true;
}
void bfs()
{
queue<State> q; q.push(start);
insert(start);
while (q.size()) {
State tmp = q.front(); q.pop();
if (finish(tmp)) { printf(" %d moves\n",tmp.g); return; }
for (int dir = 0 ; dir < 4 ; ++dir) {
State now = tmp;//.cpy();
expand(now,dir,q);
}
}
printf(" impossible\n");
}
int main()
{
int k = 0;
while (scanf("%d%d%d",&n,&m,&w)==3,n+m+w) {
++k;
input();
printf("Case %d:",k);
bfs();
printf("\n");
}
}
N×N unit squares, and
M of those unit squares contain holes. Marbles and holes are numbered from 1 to
M . The goal of the Marble game is to roll each marble into the hole that has the same number.
A game board may contain walls. Each wall is one unit long and stands between two adjacent unit squares. Two squares are considered adjacent if and only if they share a side.
At the beginning of the game, all marbles are placed on the board, each in a different square. A ``move" consists of slightly lifting a side of the game board. Then all marbles on the board roll downward toward the opposite side, each one rolling until it
meets a wall or drops into an empty hole, or until the next square is already occupied by another marble. Marbles roll subject to the following restrictions:
Marbles cannot jump over walls, other marbles, or empty holes.
Marbles cannot leave the board. (The edge of the board is a wall.)
A unit square can contain at most a single marble at any one time.
When a marble moves into a square with a hole, the marble drops into that hole. The hole is then filled, and other marbles can subsequently roll over the hole. A marble in a hole can never leave that hole.
The game is over when each marble has dropped into a hole with the corresponding number.
The figure below illustrates a solution for a game played on a
4×4 board with three blue marbles, three holes and a wall. The solution has five moves: lift the east side, lift the north side, lift the south side, lift the west side, lift the north side.
Your program should determine the fewest number of moves to drop all the marbles into the correct holes -- if such a move sequence is possible.
Input
The input file contains several test cases. The first line of each test case contains three numbers: the sizeN (2
N
4)
of the board, the number M
(M > 0) of marbles, and the number W of walls. Each of the following
2M lines contains two integers. The first integer is a row location and the second is a column location. The first
M of those lines represent the locations of the marbles, where marble#1 is on the first line, marble#2 on the second, and so on. The last
M of those lines represent the locations of the holes, with the location of hole#1 coming first, hole#2 coming second, and so on. Finally, the next
W lines represent the wall locations. Each of those lines contains four integers: the first pair are the row and column of the square on one side of the wall and the second pair are the row and column of the square on the
other side of the wall. Rows and columns are numbered 0..N - 1 .
The input file ends with a line containing three zeroes.
Output
For each test case, print the case number (beginning with 1) and the minimal number of moves to win the game. If the game cannot be won, print the word ``impossible". Put a blank line after each test case. Use the format of the sample output below.Sample Input
4 3 1 0 1 1 0 1 2 2 3 2 1 3 2 1 1 1 2 3 2 2 0 0 0 1 0 2 2 0 2 0 1 0 2 0 2 1 0 0 0
Sample Output
Case 1: 5 moves Case 2: impossible
题意:每一次能将所有的球往上下左右一个方向移动到不能移动。如果球进了洞,其他球可以从这个洞上面通过。问最少步数。
思路:直接宽搜,不过写的比较复杂啊。。。判重和状态转移都很麻烦。。比赛遇到这样的题的话,对我来说简直就是灾难,如果能过,倒还好,如果写出来了但是不过就直接崩溃了。这里面move不会因为单复数而WA的,所以不用担心。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
#define LL long long
const int maxs = 100007;
int n , m , w;
struct Point
{
Point(int rr,int cc , int v) : val(v) , r(rr) , c(cc) { }
bool operator<(const Point & p) const { return val < p.val; }
bool operator == (const Point & p) const { return r==p.r && c==p.c; }
int val;
int r;
int c;
};
inline bool cmp0(const Point&p1,const Point&p2) { return p1.r < p2.r; }
inline bool cmp1(const Point&p1,const Point&p2) {return p1.c > p2.c; }
inline bool cmp2(const Point&p1,const Point&p2) {return p1.r > p2.r; }
inline bool cmp3(const Point&p1,const Point&p2) {return p1.c < p2.c; }
int hole[7][7];
const int Move[2][4] = { {-1,0,1,0},{0,1,0,-1} };
bool cango[7][7][4];
struct State
{
State cpy() const {
State s;
s.ball = ball;
s.g = g;
memcpy(s.ocp,ocp,sizeof(s.ocp));
return s;
}
bool equals(State & st) const {
State tmp = *this;
sort(tmp.ball.begin(),tmp.ball.end());
sort(st.ball.begin(),st.ball.end());
for (int i = 0 ; i < tmp.ball.size() ; ++i)
{
if (tmp.ball[i]==st.ball[i]) continue;
return false;
}
return true;
}
vector<Point> ball;
bool ocp[7][7];
int g;
}start;
vector<State> hsh[maxs];
int key(const State & st)
{
LL ret = 0;
for (int i = 0 ; i < st.ball.size() ; ++i)
ret += 1313*(((LL)st.ball[i].r*1313+st.ball[i].c*13)*st.ball[i].val)%maxs;
return ret % maxs;
}
bool vis(State & st)
{
int k = key(st);
for (int i = 0 ; i < hsh[k].size() ; ++i)
if (st.equals(hsh[k][i])) return true;
return false;
}
void insert(const State & st)
{
int k = key(st);
hsh[k].push_back(st);
}
void input()
{
for (int i = 0 ; i < maxs ; ++i) hsh[i].clear();
for (int i = 0 ; i < n ; ++i)
for (int j = 0 ; j < n ; ++j)
for (int k = 0 ; k < 4 ; ++k)
cango[i][j][k] = true;
for (int i = 0 ; i < n ; ++i) cango[i][0][3] = false;
for (int i = 0 ; i < n ; ++i) cango[0][i][0] = false;
for (int i = 0 ; i < n ; ++i) cango[i][n-1][1] = false;
for (int i = 0 ; i < n ; ++i) cango[n-1][i][2] = false;
start.ball.clear();
memset(start.ocp,false,sizeof(start.ocp));
start.g = 0;
memset(hole,-1,sizeof(hole));
for (int i = 0 ; i < m ; ++i) {
int r , c;
scanf("%d%d",&r,&c);
start.ball.push_back(Point(r,c,i+1));
start.ocp[r][c] = true;
}
for (int i = 0 ; i < m ; ++i) {
int r , c;
scanf("%d%d",&r,&c);
start.ocp[r][c] = true;
hole[r][c] = i+1;
}
for (int i = 0 ; i < w ; ++i) {
int r1 , c1 , r2,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if (r1+1==r2) { cango[r1][c1][2] = cango[r2][c2][0] = false; }
if (r1-1==r2) { cango[r1][c1][0] = cango[r2][c2][2] = false; }
if (c1+1==c2) { cango[r1][c1][1] = cango[r2][c2][3] = false; }
if (c1-1==c2) { cango[r1][c1][3] = cango[r2][c2][1] = false; }
}
}
void expand(State & st,int k,queue<State>&q)
{
if (k==0) sort(st.ball.begin(),st.ball.end(),cmp0);
else if (k==1) sort(st.ball.begin(),st.ball.end(),cmp1);
else if (k==2) sort(st.ball.begin(),st.ball.end(),cmp2);
else sort(st.ball.begin(),st.ball.end(),cmp3);
++st.g;
for (int i = 0 ; i < st.ball.size() ; ++i) {
Point & p = st.ball[i];
int r = p.r , c = p.c;
if (hole[r][c]==p.val) continue;
int rr = r , cc = c;
while (true) {
if (!cango[rr][cc][k]) break;
rr += Move[0][k];
cc += Move[1][k];
if (st.ocp[rr][cc]) {
if (hole[rr][cc]!=-1) {
if (hole[rr][cc]!=p.val) return;
else break;
}
rr -= Move[0][k];
cc -= Move[1][k];
break;
}
}
st.ocp[r][c] = false;
if (hole[rr][cc]!=p.val) st.ocp[rr][cc] = true;
else st.ocp[rr][cc] = false;
p.r = rr , p.c = cc;
}
if (vis(st)) return;
insert(st);
q.push(st);
}
bool finish(const State & st)
{
for (int i = 0 ; i < st.ball.size() ; ++i) {
const Point & p = st.ball[i];
if (hole[p.r][p.c]!=p.val) return false;
}
return true;
}
void bfs()
{
queue<State> q; q.push(start);
insert(start);
while (q.size()) {
State tmp = q.front(); q.pop();
if (finish(tmp)) { printf(" %d moves\n",tmp.g); return; }
for (int dir = 0 ; dir < 4 ; ++dir) {
State now = tmp;//.cpy();
expand(now,dir,q);
}
}
printf(" impossible\n");
}
int main()
{
int k = 0;
while (scanf("%d%d%d",&n,&m,&w)==3,n+m+w) {
++k;
input();
printf("Case %d:",k);
bfs();
printf("\n");
}
}
相关文章推荐
- UVA 1063|11318|UVALive 3807|Marble Game|搜索
- 用bfs和dfs建树--uva10410 Tree reconstruction
- UVA 816 bfs
- uva 10891 Game of Sum (DP)
- Colour Hash (Uva 704 双向bfs)
- UVALive - 7715 Guessing Game
- UVa 1599 Ideal Path【BFS】
- sg函数_______A Funny Stone Game(uva 1378)
- UVa 10474 - Where is the Marble?
- UVA 494 Kindergarten Counting Game
- uva 11489 Integer Game
- A Dicey Problem (Uva 810 & poj 1872 bfs)
- Uva 10474 Where is the Marble?
- UVA 10474 Where is the Marble?
- UVA 10474 Where is the Marble?【vector的sort用法】
- uva 10047 The Monocycle (BFS)
- 大理石在哪儿(Where is the marble?,UVa 10474)
- UVA 10968 - KuPellaKeS 【BFS】
- UVA 1548 - The Game of Master-Mind(dfs剪枝)
- UVA - 10400 Game Show Math