码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5335 Walk Out(dfs+递推)

时间:2015-08-03 11:35:00      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:

题意:大致意思是给一个n*m的01矩阵,起点为左上方(1,1),终点为右下方(n,m),求从左上方到右下方字典序自小的路径,如果路径都为0,则输出0。


分析:首先字典序最小,先要满足路径最短,再满足路径的值最小,路径最短的毫无疑问是越靠下或者越靠右,而且如果路径的前面为0,则可以认为是以第一个非0的点的为起点。因此这题可以转化为:先找出以起点为中心的连续为零的集合,再在其中找出x+y最大的一些点为起点,(当然如果s[1][1]==1,起点就是左上方),然后以这些点不断往下往右寻找下一排的最小值,然后以下一排的最小值的为起点的所有点再往下递推,直到终点。(这里每一排的递推的起点和终点推理可以画图推出),也就是用dfs搜四个方向,递推两个方向向下和向右。

图中的点值为x+y,当tot=2时,下一排的x的起点为tot-m>=tot-m?1为1,终点为i-n<=1?i-1:n,为1,后面的斜排同理

2 3 4
3 4 5
4 5 6
 

注意:之前博客提到的,由于这里用到dfs,而且栈最大要开4000000,(但是用bfs写就不需要了)所以在hdu交的话要手动扩栈,而且要用c++交。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include<vector>
#pragma comment(linker,"/STACK:1024000000,1024000000") //手动扩栈
using namespace std;
const int maxn = 1e3+5;
int n,m;
int tot;
char s[maxn][maxn];
bool vis[maxn][maxn];
void dfs(int x,int y)
{
    if(vis[x][y]||s[x][y]-'0') return;//边界条件
    vis[x][y]=1;                      //能走到的点标记
    if(x+y>tot) tot=x+y; //标记最靠下的斜线的x+y
    if(x<n) dfs(x+1,y);  //向下
    if(x>1) dfs(x-1,y);  //向上
    if(y<m) dfs(x,y+1);  //向右
    if(y>1) dfs(x,y-1);  //向左
}
void solve()
{
    if(s[1][1]=='1'){
        printf("1");
        vis[1][1]=1;
    }
    else if(s[1][1]=='0'&&tot==m+n){
        printf("0");
    }
    for(int i=tot;i<n+m;i++){
        int nw = 1;
        for(int j=(i-m>=1?i-m:1);j<=(i-n<=1?i-1:n);j++){//斜线的初始点到终点
            int nx = j;
            int ny = i-j;
            if(vis[nx][ny]){//由上一排得到能走的点
                if(nx<n) nw = min(s[nx+1][ny]-'0',nw);//右边
                if(ny<m) nw = min(s[nx][ny+1]-'0',nw);//下边
            }
        }
        for(int j=(i-m>=1?i-m:1);j<=(i-n<=1?i-1:n);j++){
            int nx = j;
            int ny = i-j;
            if(vis[nx][ny]){
                if(nx < n && s[nx+1][ny]-'0'==nw) vis[nx+1][ny]=1;//标记下一排能走的点
                if(ny < m && s[nx][ny+1]-'0'==nw) vis[nx][ny+1]=1;
            }
        }
        printf("%d",nw);
    }
    printf("\n");
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        memset(vis,0,sizeof(vis));
        tot=2;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
        dfs(1,1);
        solve();
    }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU5335 Walk Out(dfs+递推)

标签:

原文地址:http://blog.csdn.net/sin_xf/article/details/47253047

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!