您的位置:首页 > 其它

UVa 1533 Moving Pegs 解题报告(暴力+码力)

2014-07-25 20:59 399 查看


1533 - Moving Pegs

Time limit: 3.000 seconds

Venture MFG Company, Inc. has made a game board. This game board has 15 holes and these holes are filled with pegs except one hole. A peg can jump over one or more consecutive peg s to the nearest empty
hole along the straight line. As a peg jump over the pegs you remove them from the board. In the following figure, the peg at the hole number 12 or the peg at the hole number 14 can jump to the empty hole number 5. If the peg at the hole number 12 is moved
then the peg at the hole number 8 is removed. Instead, if the peg at the hole number 14 is moved then the peg at the hole number 9 is removed.



Write a program which find a shortest sequence of moving pegs to leave the last peg in the hole that was initially empty. If such a sequence does not exist the program should write a message ``IMPOSSIBLE".

Input 

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case is a
single integer which means an empty hole number.

Output 

For each test case, the first line of the output file contains an integer which is the number of jumps in a shortest sequence of moving pegs. In the second line of the output file, print a sequence of
peg movements. A peg movement consists of a pair o f integers separated by a space. The first integer of the pair denotes the hole number of the peg that is moving, and the second integer denotes a destination (empty) hole number.
If there are multiple solutions, output the lexicographically smallest one.

Sample Input 

1
5


Sample Output 

10
12 5 3 8 15 12 6 13 7 9 1 7 10 8 7 9 11 14 14 5


    解题报告:一道“简单”题,随便BFS一下不就行了?不过这简单的搜索题依然感人至深,因为不好实现。推荐作为练码力的题目。

    不好搞的地方在于:如何枚举当前要移动的点,移动的终点,并且使它满足字典序最低。以及如何修改状态。

    这里我的做法是,首先按起点字典序优先枚举出所有的移动路径。比如从点1经过点2移动到点4,这个路径记录为1->2->4,使用二进制表示,为000000000001011。因为在二进制上体现不出方向,我们还要另外保存起点sta和终点end。

    当n=5时,初始状态为st  =111111111101111。我们枚举所有可能的路径line,如果st & line = line ^ (1<<end),说明在整条路径上,除了终点其他地方都是填充的。这刚好符合我们的需求,转移过来的状态就是st ^ line。同时保存起点终点到路径里。当第一次找到结束状态,break出来输出答案就好了。

    手写转移过程当然也是可行的,不过太过复杂了。所有可能的路径有60条……

    贴个代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define bit(n) (1<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
freopen("in.txt", "r", stdin);
#endif // ACM
work();
}

/***************************************************/
int tot = 0;
int line[111];
int Sta[111];
int End[111];
int lineEnd[111111];

void init()
{
int no = 0;
int row[15];
int col[15];
int maze[10][10];
fff(i, 1, 5) fff(j, 1, i)
{
maze[i][j] = no;
row[no] = i;
col[no] = j;
no++;
}

ff(i, 15) ff(j, 15)
{
if(row[i] == row[j] && abs(col[i]-col[j]) >= 2)
{
int st = 0;

if(col[j] > col[i])
fff(k, col[i], col[j])
st ^= bit(maze[row[i]][k]);
else
dff(k, col[i], col[j])
st ^= bit(maze[row[i]][k]);

line[tot] = st;
Sta[tot] = maze[row[i]][col[i]];
End[tot] = maze[row[j]][col[j]];
tot++;
}

if(col[i] == col[j] && abs(row[i]-row[j]) >= 2)
{
int st = 0;

if(row[j] > row[i])
fff(k, row[i], row[j])
st ^= bit(maze[k][col[i]]);
else
dff(k, row[i], row[j])
st ^= bit(maze[k][col[i]]);

line[tot] = st;
Sta[tot] = maze[row[i]][col[i]];
End[tot] = maze[row[j]][col[j]];
tot++;
}

if(abs(row[i]-row[j]) >= 2 && row[i]-row[j] == col[i]-col[j])
{
int st = 0;

int dis = row[j]-row[i];
if(dis > 0)
fff(k, 0, dis)
st ^= bit(maze[row[i]+k][col[i]+k]);
else
dff(k, 0, dis)
st ^= bit(maze[row[i]+k][col[i]+k]);

line[tot] = st;
Sta[tot] = maze[row[i]][col[i]];
End[tot] = maze[row[j]][col[j]];
tot++;
}
}
}

struct Node
{
int st;
vector<int> path;
} x, y;

int id;
int vis[bit(15)];

void work()
{
init();

int T;
scanf("%d", &T);
fff(cas, 1, T)
{
int n;
scanf("%d", &n);
n--;

++id;
x.st = (bit(15)-1)^bit(n);
x.path.clear();
vis[x.st] = id;

queue<Node> que;
que.push(x);

while(que.size())
{
x = que.front();
que.pop();

if(x.st == bit(n)) break;

ff(i, tot)
{
int state = line[i];

if((x.st & state) == (state ^ bit(End[i])))
{
y.st = (x.st ^ state);

if(vis[y.st] == id) continue;
vis[y.st] = id;

y.path = x.path;
y.path.push_back(Sta[i]);
y.path.push_back(End[i]);
que.push(y);
}
}
}

if(x.st == bit(n))
{
int s = x.path.size();
printf("%d\n", s/2);
printf("%d", x.path[0]+1);
fff(i, 1, s-1) printf(" %d", x.path[i]+1);
puts("");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: