您的位置:首页 > 其它

USACO 4.4.1 Shuttle Puzzle 棋盘游戏 题解与分析

2013-09-17 21:52 423 查看
Shuttle Puzzle棋盘游戏译 by Jeru

描述

大小为3的棋盘游戏里有3个白色棋子,3个黑色棋子,和一个有7个格子一线排开的木盒子。3个白棋子被放在一头,3个黑棋子被放在另一头,中间的格子空着。
初始状态: WWW_BBB
目标状态: BBB_WWW
在这个游戏里有两种移动方法是允许的:你可以把一个棋子移到与它相邻的空格;你可以把一个棋子跳过一个(仅一个)与它不同色的棋子到达空格。大小为N的棋盘游戏包括N个白棋子,N个黑棋子,还有有2N+1个格子的木盒子。这里是3-棋盘游戏的解,包括初始状态,中间状态和目标状态:
WWW BBB
WW WBBB
WWBW BB
WWBWB B
WWB BWB
W BWBWB
WBWBWB
BW WBWB
BWBW WB
BWBWBW
BWBWB W
BWB BWW
B BWBWW
BB WBWW
BBBW WW
BBB WWW
请编一个程序解大小为N的棋盘游戏(1 <= N <= 12)。要求用最少的移动步数实现。

格式

PROGRAM NAME: shuttleINPUT FORMAT:(file shuttle.in)一个整数N。OUTPUT FORMAT:(file shuttle.out)输出用移动的棋子在棋盘的位置(位置从左到右依次为1, 2, ..., 2N+1)表示的变换序列,每个数字之间以空格分隔,每行20个数(除了最后一行)。输出的解还应当有最小的字典顺序(即如果有多组移动步数最小的解,输出第一个数最小的解;如果还有多组,输出第二个数最小的解;...)。

SAMPLE INPUT

3

SAMPLE OUTPUT

3 5 6 4 2 1 3 5 7 6 4 2 3 5 4
【分析】:
DFS优化。首先,对一个长度为2*N+1的数组染色<在程序中1代表W,2代表B>,然后DFS,为满足字典序最小,那么顺序应该为:右2<空格左移2>→右1<空格左移1>→左1<空格右移1>→左2<空格右移2>,这样保证空格的位置的字典序最小。由公式推导,最小步数为N*(N+2),即DFS的层数为N*(N+2)。在移动过程中的优化:然后看W和B的整体移动方向:W整体向右移,B整体向左移,那么可以优化为W只向右移,B只向左移,这样程序效率也很不错
【代码】:
/*
ID:csyzcyj1
PROG:shuttle
LANG:C++
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define MAX 180
#define IMAX 21474836
int N;
int now[MAX],ans[MAX];
void pre_makestring()
{
for(int i=1;i<=N;i++)
now[i]=1;//1代表‘W’
for(int i=N+2;i<=2*N+1;i++)
now[i]=2;//2代表‘B’
}
void swap(int &x,int &y){int t;t=x,x=y,y=t;}
void putout()
{
int tot=0;
for(int i=1;i<=N*(N+2);i++)
{
if(tot%20==0)
printf("%d",ans[i]);
else printf(" %d",ans[i]);

tot++;
if(tot%20==0)
printf("\n");
}
if(tot%20)   printf("\n");
}
void work(int empty,int floor)
{
if(empty-2>0 && now[empty-2]==1 && now[empty-1]==2)//向右跳两格
{
swap(now[empty-2],now[empty]);
ans[floor]=empty-2;
if(floor==N*(N+2) && empty-2==N+1)  {putout();return;}
else if(floor<N*(N+2))
work(empty-2,floor+1);
swap(now[empty-2],now[empty]);
}
if(empty-1>0 && now[empty-1]==1)//向右跳一格
{
swap(now[empty-1],now[empty]);
ans[floor]=empty-1;
if(floor==N*(N+2) && empty-1==N+1)  {putout();return;}
else if(floor<N*(N+2))
work(empty-1,floor+1);
swap(now[empty-1],now[empty]);
}
if(empty+1<=2*N+1 && now[empty+1]==2)//向左跳一格
{
swap(now[empty+1],now[empty]);
ans[floor]=empty+1;
if(floor==N*(N+2) && empty+1==N+1)  {putout();return;}
if(floor<N*(N+2))
work(empty+1,floor+1);
swap(now[empty+1],now[empty]);
}
if(empty+2<=2*N+1 && now[empty+2]==2 && now[empty+1]==1)//向左跳两格
{
swap(now[empty+2],now[empty]);
ans[floor]=empty+2;
if(floor==N*(N+2) && empty+2==N+1)  {putout();return;}
if(floor<N*(N+2))
work(empty+2,floor+1);
swap(now[empty+2],now[empty]);
}
}
int main()
{
freopen("shuttle.in","r",stdin);
freopen("shuttle.out","w",stdout);
scanf("%d",&N);
pre_makestring();
work(N+1,1);
//system("pause");
return 0;
}
【评测信息】:        TASK: shuttle        LANG: C++        Compiling...        Compile: OK        Executing...        Test 1: TEST OK [0.011 secs, 3376 KB]        Test 2: TEST OK [0.011 secs, 3376 KB]        Test 3: TEST OK [0.011 secs, 3376 KB]        Test 4: TEST OK [0.011 secs, 3376 KB]        Test 5: TEST OK [0.000 secs, 3376 KB]        Test 6: TEST OK [0.000 secs, 3376 KB]        Test 7: TEST OK [0.011 secs, 3376 KB]        Test 8: TEST OK [0.011 secs, 3376 KB]        Test 9: TEST OK [0.011 secs, 3376 KB]        Test 10: TEST OK [0.011 secs, 3376 KB]        All tests OK. 转载注明出处:http://blog.csdn.net/u011400953

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