zoukankan      html  css  js  c++  java
  • zoj(2110)Tempter of the Bone(DFS+奇偶剪枝)

    剪枝很重要,可走的格数小于时间则减去,然后就是奇偶性剪枝
    可以把map看成这样:
    0 1 0 1 0 1
    1 0 1 0 1 0
    0 1 0 1 0 1
    1 0 1 0 1 0
    0 1 0 1 0 1
    从为 0 的格子走一步,必然走向为 1 的格子
    从为 1 的格子走一步,必然走向为 0 的格子
    即:
     0 ->1或1->0 必然是奇数步
     0->0 走1->1 必然是偶数步
    所以当遇到从 0 走向 0 但是要求时间是奇数的,或者, 从 1 走向 0 但是要求时间是偶数的 都可以直接判断不可达!

    #include <iostream>
    #include <stdio.h>
    #include <string>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    #include <fstream>
    #include <vector>
    #include <map>
    #include <queue>
    #include <stack>
    #include <math.h>
    #include <stdlib.h>
    using namespace std ;
    const int maxn = 55;
    char grid[maxn][maxn];
    int vis[maxn][maxn];
    int n,m,s,flag;
    int sx,sy,dx,dy;
    int dir[4][2] = {1,0,0,1,-1,0,0,-1};
    int cango(int x,int y){
        return x>=1&&x<=n&&y>=1&&y<=m;
    }
    void dfs(int x,int y,int step){
        if(flag)return ;//也是一种剪枝吧,不加上这句险些TLE
        if(step == s){
            if(x == dx && y == dy)
                flag = 1;
            return;
        }
        int temp = s - step - abs(dy - y)-abs(dx - x);
        if(temp<0||temp&1)//奇偶剪枝
            return;
        for(int i = 0;i < 4;i++){
            int xx = x + dir[i][0];
            int yy = y + dir[i][1];
            if(cango(xx,yy)&&!vis[xx][yy]&&grid[xx][yy] != 'X'){
                vis[xx][yy] = 1;
                dfs(xx,yy,step+1);
                vis[xx][yy] = 0;
            }
        }
    }
    int main(){
        while(scanf("%d%d%d",&n,&m,&s)&&(n+m+s)){
            int wall = 0;
            for(int i = 1;i <= n;i++)
                scanf("%s",grid[i]+1);
            for(int i = 1;i <= n;i++)
                for(int j = 1;j <= m;j++){
                    if(grid[i][j] == 'S'){
                        sx = i;
                        sy = j;
                    }
                    if(grid[i][j] == 'D'){
                        dx = i;
                        dy = j;
                    }
                    if(grid[i][j] == 'X') wall++;
                }
            if(n*m - wall <= s){//可能性剪枝
                printf("NO\n");
                continue;
            }
            flag = 0;
            memset(vis,0,sizeof(vis));
            vis[sx][sy] = 1;
            dfs(sx,sy,0);
            if(flag)
                printf("YES\n");
            else
                printf("NO\n");
            //for(int i = 1;i <= n;i++)
              //  printf("%s\n",grid[i]+1);
        }
        return 0 ;
    }
  • 相关阅读:
    Jzoj2682 最长双回文串
    Jzoj2682 最长双回文串
    【hdu3853】Loops
    【tyvj1015】【caioj1060】公路乘车
    【luogu1064】金明的预算方案
    【bzoj1260】【CQOI2007】涂色paint
    【UVa1629】Cake slicing
    【NYOJ746】整数划分(四)
    【NYOJ 15】括号匹配2
    【poj2955】Brackets
  • 原文地址:https://www.cnblogs.com/Roly/p/3056980.html
Copyright © 2011-2022 走看看