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

56 篇文章 0 订阅

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.

\epsfbox{p2093.eps}

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("");
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值