NYOJ 692 Chinese checkers(广搜)

Chinese checkers

时间限制:1000 ms  |  内存限制:65535 KB
难度:2
描述

I think almost everyone play Chinese checkers when we were young. 


Recently, hft777 is fond of playing Chinese checkers. But he is puzzled with how many steps at least to move all his pieces to his opposite position.

To make the problem simple, now we take a line into account. There are n positions on a line, numbered from 0 to n-1.At fast, two same balls is on 0 and 1 position, and every time you can move a ball left or right, or you can move a ball on the position x to the position z on the other side of the ball on the position y, and |x-y|=|y-z|. And you must mark sure the ball can’t move out of the bounder, and the two balls can’t be on one same position. Now, hft777 wants to how many steps at least to move the two same to the n-2, n-1 positions.


输入
The first line of the input is one integer t, the number of testcase.
For each testcase, one integer n for a line, corresponding to the length of the line. 2≤n<1000 
输出
For each testcase output the minimum steps.
样例输入
2
3
4
样例输出
1
2

比赛时一直在找规律,但是因为推出的数据有点少,根据这些数据推出的规律是错的。虽然比赛时也想到了用广搜写,但是害怕超时就没尝试。现在想想真有点后悔,当时应该试试的。

题意:跳棋。有n个位置,从0~n-1编号,开始时两个球分别在0、1位置,目标状态是两个球在n-2、n-1位置。对于每次操作,可以向左(即向后)走一步,可以向右(即向前)走1步,也可以使一个球跳过另外一个球,跳之前的位置和调之后的位置距离另外一个球的距离相等,且每次操作都必须在0~n-1范围内。问从0、1位置到n-2、n-1位置最少需要操作多少次。

分析:用广搜把所有可能出现的情况都求出来,之后每输入一个值,直接输出答案即可。

用数组模拟队列:

//step[i][j]记录两个球分别到达i、j点的最小步数
//step[i][j]=0时表示后面的球在i位置、前面的球在j位置这个状态没有出现过
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1010;
int step[N][N];
int que[N*N][2];
int head, tail;

void bfs(int n)
{
    int x, y, nx, ny;
    memset(step, 0, sizeof(step));
    step[0][1] = 0;
    que[0][0] = 0;
    que[0][1] = 1;
    head = 0;
    tail = 1;
    while(head < tail)
    {
        x = que[head][0];
        y = que[head++][1];
        if((x == n - 1 && y  == n - 2) || (x == n - 2 && y == n - 1))
            return ;
        int mmax = max(x, y);
        int mmin = min(x, y);
        x = mmin;
        y = mmax;
        if(x - 1 > 0) //后面的球向后走1步
        {
            nx = x - 1;
            ny = y;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
        if(x + 1 < n && x + 1 != y) //后面的球向前走1步
        {
            nx = x + 1;
            ny = y;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
        if(y - 1 > 0 && y - 1 != x) //前面的球向后走1步
        {
            nx = x;
            ny = y - 1;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
        if(y + 1 < n) //前面的球向前走一步
        {
            nx = x;
            ny = y + 1;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
        if(y * 2 - x < n) //后面的球跨过前面的球向前跳
        {
            nx = y;
            ny = y * 2 - x;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
        if(x * 2 - y >= 0) //前面的球跨过后面的球向后跳
        {
            nx = x * 2 - y;
            ny = x;
            if(!step[nx][ny])
            {
                step[nx][ny] = step[x][y] + 1;
                que[tail][0] = nx;
                que[tail++][1] = ny;
            }
        }
    }
}

int main()
{
    int T, n;
    bfs(1005);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        if(n == 2)
            printf("0\n");
        else
            printf("%d\n", step[n-2][n-1]);
    }
    return 0;
}

用STL里面的队列:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;

const int N = 1010;
struct node
{
    int x;
    int y;
};
int step[N][N];

void bfs(int n)
{
    queue <node> que;
    node a, b, c;
    memset(step, 0, sizeof(step));
    a.x = 0;
    a.y = 1;
    que.push(a);
    while(!que.empty())
    {
        b = que.front();
        que.pop();
        int x = min(b.x, b.y);
        int y = max(b.x, b.y);
        if((x == n - 1 && y == n - 2) || (x == n - 2 && y == n - 1))
            return ;
        if(x - 1 > 0)  //后面的球向后走1步
        {
            int nx = x - 1;
            int ny = y;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
        if(x + 1 < n && x + 1 != y)   //后面的球向前走1步
        {
            int nx = x + 1;
            int ny = y;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
        if(y - 1 != x && y - 1 > 0)  //前面的球向后走1步 
        {
            int nx = x;
            int ny = y - 1;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
        if(y + 1 < n)   //前面的球向前走一步
        {
            int nx = x;
            int ny = y + 1;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
        if(y * 2 - x < n)   //后面的球跨过前面的球向前跳
        {
            int nx = y;
            int ny = y * 2 - x;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
        if(x * 2 - y > 0)   //前面的球跨过后面的球向后跳 
        {
            int nx = x * 2 - y;
            int ny = x;
            if(!step[nx][ny])
            {
                c.x = nx;
                c.y = ny;
                que.push(c);
                step[nx][ny] = step[x][y] + 1;
            }
        }
    }
}

int main()
{
    bfs(1005);
    int T, n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        if(n == 2)
            printf("0\n");
        else
            printf("%d\n",step[n-2][n-1]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值