【POJ2488】 A knight's Journey 解题报告 测试数据+代码+思路

7 篇文章 0 订阅
5 篇文章 0 订阅
 
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <iostream>
//#define INPUT
//#define DBG
/**
    Problem:POJ2488
    Begin Time:8th/Mar/2012 1:30 p.m.
    End Time:2012-03-08 21:08:53
    Test Data:见下方另一份代码,数据生成器
    Standard output:以本程序对拼即可。
    知识点:深度优先搜索+回溯,在搜索方向选择上还考了一个小小的贪心法
    思路:
        Recursive BFS即可。
        以一个数组track记录当前的路径。
        indtrack记录当前track数组中有多少个元素
        当indtrack = p*q的时候退出
        搜索的时候记得向量要按照字母序,也就是说,以-2最为优先,然后是-1
        然后是1,然后是2
        本解题报告中,x为字母(A..Z),y为数字(1...26)
    教训:
    1.BFS不保证遍历全图,所以记得回溯,因为这个WA了8个小时(在这个条件是的,如果是上下左右4方向或

者8方向的那种,则应该可以不回溯)
    2.BFS在要用回溯的时候,不熟练的时候千万别用stack,最好还是老老实实递归
    3.记录track的时候不可以用STL里面的queue,因为queue.pop始终是pop最顶层元素
    在某一层递归回溯的时候,pop的可能是其他递归放进去的元素,导致不出最优解。
    4.WA的时候,按照自己的思路走一遍代码,确认没问题的时候再看细节
    5.写搜索的时候要仔细,第一次把搜索向量的 < 8写成了 < 7,导致WA
    6.千万别手懒,其实最好按照自己的思路写几个测试数据试一试再写代码。
    7.递归出结果的时候,尤其是这种要记录路径的,不要直接在递归函数里写,要设置一个
    全局布尔变量,然后根据其取值写,这样做得好处是
    (1)避免了重复输出,因为trackind == p * q的时候可能有一些递归还没有return,会导致重复输出
    (2)便于输出和判断是否impossible
    (3)在isPossible = true的时候所有递归return,节省了时间。
    c0de4fun,A AC a day keeps WA away.
*/
using namespace std;
const int c0de4fun = 30;
int movex[8] = {-2,-2,-1,-1,1,1,2,2};
int movey[8] = {-1,1,-2,2,-2,2,-1,1};
int maze[c0de4fun][c0de4fun];
int cntvisited = 0;
bool isPossible = false;
struct node
{
    int x;
    int y;
};
//queue<node> track;
int track[100][3];
int trackind = 0;
void DFS(int X,int Y,int nowx,int nowy)
{
    node tmp;
    node tmp1;
    int tracknow;
    tmp.x = nowx;
    tmp.y = nowy;
    cntvisited++;
    maze[tmp.x][tmp.y] = 1;
    tracknow = trackind;
    if(!isPossible)
    {
    track[tracknow][1] = tmp.x;
    track[tracknow][2] = tmp.y;
    trackind++;
    }
    else
    {
        return;
    }

#ifdef DBG
    printf("Now visit the %c%d \n",tmp.x - 1 + 'A',tmp.y);
#endif
    if( cntvisited == X*Y )
    {
        isPossible = true;
       /* for(int i = 0 ; i < trackind ; i++)
        {
            printf("%c%d",track[i][1] - 1 + 'A',track[i][2]);
        }
        printf("\n");
        return; */
    }
    for(int i = 0 ; i < 8 ; i++)
    {
        tmp1.x = tmp.x + movex[i];
        tmp1.y = tmp.y + movey[i];
        if( tmp1.x > X || tmp1.y > Y
           || tmp1.x < 1 || tmp1.y < 1
           || maze[tmp1.x][tmp1.y] == 1)
           continue;
        DFS(X,Y,tmp1.x,tmp1.y);
    }
    cntvisited--;maze[tmp.x][tmp.y] = 0;
    if(!isPossible)
    {
    track[tracknow][1] = 0 ;
    track[tracknow][2] = 0;
    trackind--;
    }

    return;
}
int main()
{
#ifdef INPUT
    freopen("b:\\acm\\poj2488\\input.txt","r",stdin);
    freopen("b:\\acm\\poj2488\\output_me.txt","w",stdout);
#endif
    int T,P,Q;
    scanf("%d",&T);
    for(int t = 0 ; t < T; t++)
    {
        printf("Scenario #%d:\n",t+1);
        cntvisited = 0;
        trackind = 0;
        isPossible = false;
        memset(track,0,sizeof(int)*200);
        memset(maze,0,sizeof(int)*c0de4fun*c0de4fun);
        scanf("%d%d",&P,&Q);
        DFS(Q,P,1,1);
        if(!isPossible)
        {
            printf("impossible\n");
        }
        else
        {
            for(int i = 0 ; i < trackind; i ++)
            {
                printf("%c%d",track[i][1] - 1 + 'A',track[i][2]);
            }
            printf("\n");
        }
        if ( t != T-1)
            printf("\n");
    }
#ifdef INPUT
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

测试数据生成代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <time.h>
using namespace std;
const int cases = 5000;
int main()
{
    freopen("b:\\acm\\poj2488\\input.txt","w",stdout);
    int a = 0;
    srand(time(NULL));
    printf("%d\n",cases);
    for(int i = 0 ; i < cases; i++)
    {
        a = rand()%26 + 1;
        printf("%d %d\n",a,26/a);
    }
    fclose(stdout);
 //   cout << "Hello world!" << endl;
    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值