UVa 1533 Moving Pegs 解题报告(暴力+码力)
2014-07-25 20:59
399 查看
1533 - Moving Pegs
Time limit: 3.000 secondsVenture 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.
![](http://uva.onlinejudge.org/external/15/2093img1.png)
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 asingle 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 ofpeg 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("");
}
}
}
相关文章推荐
- UVa 225 - Golygons 解题报告(暴力)
- UVa 10318 Security Panel 解题报告(暴力,中途相遇法)
- UVa 120 - Stacks of Flapjacks 解题报告(暴力)
- UVa 669 - Defragment 解题报告(暴力)
- UVa 387 - A Puzzling Problem 解题报告(暴力)
- UVa 110 Meta-Loopless Sorts 解题报告(暴力)
- UVa 10317 Equating Equations 解题报告(暴力)
- UVa 269 Counting Patterns 解题报告(暴力)
- UVa 140 - BandWidth 解题报告(暴力)
- UVa 165 - Stamps 解题报告(暴力)
- codeforces 158D 解题报告 数论+暴力
- 【解题报告】uva10405_Longest Common Subsequence(最长公共子序列, dp)
- 【解题报告】uva10066_The Twin Towers(双塔, dp, LCS)
- UVa 540 Team Queue解题报告
- 一中OJ #1434 序列的LCS [UVa 10635 -> Prince and Princess] | 动态规划 LCS映射转换LIS | 解题报告
- hdu 5547 Sudoku dfs 暴力回溯 解题报告
- uva548解题报告
- UVA1615 高速公路(highway)(重庆一中高2018级信息学竞赛测验5) 解题报告
- UVa 11100 The Trip, 2007 解题报告(策略)
- UVa 1325 Hypertransmission 解题报告(扫描线)