zoukankan      html  css  js  c++  java
  • POJ 2922

    Honeymoon Hike

    题目链接;

    参考博客

    https://blog.csdn.net/u013480600/article/details/26097213

    解题思路

    这道题主要使用了搜索,二分,枚举算法,
    对于搜索:DFS的时间复杂度为O(V+E),V <= 10000 ,E <= 40000;
    对于二分:时间复杂度 为 lg(n); n<=200;
    对于枚举:时间复杂度为 :O(n); n <= 200;
     所以总体的计算量上限为 :8 * 200 *  50000 = 8 * 10^7;
    题目要求的时间限制为:5s;大约的计算量为5 * 10^7;
    基本满足题目要求;
    

    实现1:非递归版DFS + 二分 + 枚举

    这里出现了超时

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <vector>
    #include <queue>
    
    using namespace std;
    int a[105][105];
    int vis[105][105];
    int n;
    #define INF 0x7fffffff
    struct Nod
    {
    	int x;
    	int y;
    	Nod(){
    	}
    };
    int x[4]={-1,1,0,0};
    int y[4]={0,0,-1,1};
    bool dfs(int si,int sj,int low,int high)
    {
    	memset(vis,0,sizeof(vis));
    	stack<Nod>st;
    	Nod tmp;
    	tmp.x = si;
    	tmp.y = sj;
    	st.push(tmp);
    	vis[si][sj] = 1;
    	if(a[si][sj] < low || a[si][sj] > high) return false;
    	while(!st.empty())
    	{
    		Nod now = st.top();
    		int nowi = now.x;
    		int nowj = now.y;
    		if(nowi == n && nowj == n) return true;
    		int ni,nj;
    		bool noFind =true;
    		for(int i = 0; i < 4; ++i)
    		{
    			ni = nowi + x[i];
    			nj = nowj + y[i];
    			if(ni > 0 && ni <= n && nj > 0 && nj <= n)
    			{
    				if(!vis[ni][nj])
    				{
    					vis[ni][nj] = 1;
    					if(!(a[ni][nj] >= low && a[ni][nj] <= high)) continue;
    					tmp.x = ni;
    					tmp.y = nj;
    					st.push(tmp);
    					noFind = false;
    					break;
    				}
    			}
    		}
    		if(noFind)
    		st.pop();
    	}
    	return false;
    }
    bool check(int low,int high,int d)
    {
    	int e = high - d;
    	for(int i = low; i <= e; ++i)
    	{
    		if(dfs(1, 1, i, i + d))
    		{
    			return true;
    		}
    	}
    	return false;
    }
    
    bool input(int order)
    {
    	scanf("%d",&n);
    	int low = INF,high = -1;
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= n; ++j)
    		{
    			scanf("%d",&a[i][j]);
    			if(a[i][j] < low)
    			{
    				low = a[i][j];
    			}else if(a[i][j] > high){
    				high = a[i][j];
    			}
    		}
    	}
    	int mid;
    	int max_d = high - low;
    	int L = 0;
    	int R = max_d + 1;
    	while(L < R)
    	{
    		mid = (L + R) >> 1;
    		if(check(low, high, mid))R = mid;
    		else L = mid + 1;
    	}
    	printf("Scenario #%d:
    ",order);
    	printf("%d
    ",R);
    	printf("
    ");
    	return true;	
    } 
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	for(int i = 1; i <= T; ++i)
    	{
    		input(i);
    	}
    	return 0;
    }
    

    实现二:递归DFS + 二分 + 枚举(通过)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <vector>
    #include <queue>
    
    using namespace std;
    int a[105][105];
    int vis[105][105];
    int n;
    #define INF 0x7fffffff
    int x[4]={-1,1,0,0};
    int y[4]={0,0,-1,1};
    bool dfs(int si,int sj,int low,int high)
    {
    	
    	if(!(a[si][sj] >= low && a[si][sj] <= high)) return false;
    	if(si == n && sj == n) return true;
    	int  nowi, nowj, ni, nj;
    	nowi = si;
    	nowj = sj;
    	for(int i = 0; i < 4; ++i)
    	{
    		ni = nowi + x[i];
    		nj = nowj + y[i];
    		if(ni > 0 && ni <= n && nj > 0 && nj <= n)
    		{
    			if(!vis[ni][nj])
    			{
    				vis[ni][nj] = 1;
    				if(dfs(ni,nj,low,high)) return true;
    			}
    		}
    	}
    	return false;
    }
    bool check(int low,int high,int d)
    {
    	int e = high - d;
    	for(int i = low; i <= e; ++i)
    	{
    		memset(vis,0,sizeof(vis));
    		if(dfs(1, 1, i, i + d))
    		{
    			return true;
    		}
    	}
    	return false;
    }
    
    bool input(int order)
    {
    	scanf("%d",&n);
    	int low = INF,high = -1;
    	for(int i = 1; i <= n; ++i)
    	{
    		for(int j = 1; j <= n; ++j)
    		{
    			scanf("%d",&a[i][j]);
    			if(a[i][j] < low)
    			{
    				low = a[i][j];
    			}else if(a[i][j] > high){
    				high = a[i][j];
    			}
    		}
    	}
    	int mid;
    	int max_d = high - low;
    	int L = 0;
    	int R = max_d + 1;
    	while(L < R)
    	{
    		mid = (L + R) >> 1;
    		if(check(low, high, mid))R = mid;
    		else L = mid + 1;
    	}
    	printf("Scenario #%d:
    ",order);
    	printf("%d
    ",R);
    	printf("
    ");
    	return true;	
    } 
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	for(int i = 1; i <= T; ++i)
    	{
    		input(i);
    	}
    	return 0;
    }
    
  • 相关阅读:
    SQL的内连接与外连接
    for,foreach,iterator的用法和区别
    StringUtils中 isNotEmpty 和isNotBlank的区别
    Context解读
    常用的加密方式
    Android中前景,背景 和 Gravity的设置属性
    使用WebView时软键盘遮挡H5页面解决办法
    Git merge Dev 分支到 master
    C#高级编程笔记 Day 5, 2016年9月 13日 (泛型)
    C#高级编程笔记 Delegate 的粗浅理解 2016年9月 13日
  • 原文地址:https://www.cnblogs.com/lif323/p/9389167.html
Copyright © 2011-2022 走看看