zoukankan      html  css  js  c++  java
  • [HDU1010] Tempter of the Bone

    题目参见:http://acm.hdu.edu.cn/showproblem.php?pid=1010

    题目大意呢,就是一只doge要从S出发正好走T步到达终点D,注意不是T步之内(这不科学)求doge是否能够跑走

    看上去就是一搜索题,这里我们讲三种方法

    1. DFS+剪枝

    DFS好不好打?好打!那就用DFS!

    可是当你打完DFS提交上去发现了Time Limit Exceeded

    看上去本题没什么剪枝的啊

    其实是有的

    既然狗要在正好T步走到D,那么,我们判断下S与D的曼哈顿距离p,再把这个p与T进行比较,如果奇偶性不同,就达不到

    = =看上去很有道理?其实就很有道理。

    这么剪枝,过了!

    贴代码

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<cmath>
    using namespace std;
    int n,m,k;
    char map[10][10];
    bool vis[10][10];
    int dx[]={1,-1,0,0};
    int dy[]={0,0,1,-1};
    bool flag=0;
    int endx,endy;
    bool check(int x, int y) {
        if (x>=1 && x<=n && y>=1 && y<=m && !vis[x][y] && map[x][y]!='X') return true;
        return false;
    }
    void newer() {
       // memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        flag=0;endx=0;endy=0;
    }
    void dfs(int step,int x,int y) {
        //if(flag) return;
        //if(step>k+1) return;
        if(step==k+1) {
            if(x==endx&&y==endy) flag=1;
            return;
        }
        for (int i=0;i<4;++i) {
            int xx=x+dx[i],yy=y+dy[i];
            if(check(xx,yy)) {
                vis[xx][yy]=1;
                dfs(step+1,xx,yy);
                if(flag) return;
                vis[xx][yy]=0;
            }
        }
    }
    int main() {
        while(~scanf("%d%d%d",&n,&m,&k)) {
            if(n==0&&m==0&&k==0) break;
            //printf("%d%d%d",n,m,k);
            newer();
            for (int i=1;i<=n;++i) {
                getchar();
                for(int j=1;j<=m;++j) scanf("%c",&map[i][j]);
            }
            int walls=0,startx,starty;
            for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) {
                if(map[i][j]=='X') walls++;
                if(map[i][j]=='S') {startx=i;starty=j;}
                if(map[i][j]=='D') {endx=i;endy=j;}
            }
            getchar();
            if(abs(startx-endx)+abs(starty-endy)>k||(starty+endy+startx+endx+k)%2==1) {
                printf("NO
    ");
                continue;
            }
    
            if(n*m-walls<k) {printf("NO
    ");continue;}
            vis[startx][starty]=1;
            dfs(1,startx,starty);
            if(flag) printf("YES
    "); else printf("NO
    ");
        }
        return 0;
    }
    View Code

    楼主的代码风格有点丑- -我得承认这点

    2. BFS

    dxy巨巨看到我DFS打跪了就鼓动我打BFS,可惜我懒,于是就想出来了上面那个剪枝。

    话说肯定有人打BFS,BFS应该不会TLE的,读者有兴趣可自己尝试下。

    3. DP

    wyh巨巨看到dxy巨巨鼓动我打BFS,就来鼓动我打DP了

    看上去确实能DP

    f[k][x][y]表示第k步能否走到[x,y]

    那么状态转移方程就很好列了,判断上下左右四次就结束了

    看上去真的很有道理

    但是因为楼主太懒,也懒得写了,于是就把DFS剪枝想出来了

    好了吐槽完了,谢谢各位看官!

    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    java 数字补齐0
    Ubuntu 12.04中文输入法的安装
    mac 更改word的默认显示比例为125
    接口测试的简介
    接口测试和功能测试的区别
    session、token、cookie的区别
    python接口自动化--get请求
    测试用例之正交排列法
    编写测试用例的方法
    jquery选择器
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/hdu1010.html
Copyright © 2011-2022 走看看