zoukankan      html  css  js  c++  java
  • HDU-1428(记忆化搜索)

    Problem Description
    LL 最近沉迷于AC不能自拔,每天寝室、机房两点一线。由于长时间坐在电脑边,缺乏运动。他决定充分利用每次从寝室到机房的时间,在校园里散散步。整个HDU 校园呈方形布局,可划分为n*n个小方格,代表各个区域。例如LL居住的18号宿舍位于校园的西北角,即方格(1,1)代表的地方,而机房所在的第三实验 楼处于东南端的(n,n)。因有多条路线可以选择,LL希望每次的散步路线都不一样。另外,他考虑从A区域到B区域仅当存在一条从B到机房的路线比任何一 条从A到机房的路线更近(否则可能永远都到不了机房了…)。现在他想知道的是,所有满足要求的路线一共有多少条。你能告诉他吗?
     
    Input
    每组测试数据的第一行为n(2=<n<=50),接下来的n行每行有n个数,代表经过每个区域所花的时间t(0<t<=50)(由于寝室与机房均在三楼,故起点与终点也得费时)。
     
    Output
    针对每组测试数据,输出总的路线数(小于2^63)。
     
    Sample Input
    3 1 2 3 1 2 3 1 2 3 3 1 1 1 1 1 1 1 1 1
     
    Sample Output
    1 6
     

    思路:
    这题再加上之前的那道老鼠题,算是记忆化搜索的模板题了,现在来学真是没觉得有什么难度,理顺了题目的思路,看了kuangbin大神的AC代码后,凭着思路在脑中复原代码修正后AC了
    题目说A->B点的要求是B点到终点的多个距离中,肯定存在一个dis是小于A点所有到终点的距离的,而A点所有到终点的距离中就会包括通过B到达终点的距离————对这种逻辑进行一下总结,就会发现它让你求的就是起点到终点相同长度最短路的条数
    知道了这点之后,我们就可以开始计算所有的最短路了
    计算最短路就是用Dijkstra,但是这个题这样做就麻烦了,其实这道题目用的方法Dijkstra是相同的,他们实质都是相同的,即每次对选入最短路线集合的点,松弛他的所有邻边。对于原始的Dij而言,我们用的for扫描整个数组,然后找出相邻的边,再对他们进行松弛操作。
    都记录了最短距离之后,在递归求得第一个点的答案。

    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    struct node {
        int x,y;
        int d;
    };
    int n;
    int map[57][57];
    int dis[57][57];
    __int64 dp[57][57];
    int vis[57][57];
    int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    
    bool operator < (node a,node b) {
        return a.d>b.d;
    }
    
    void dfs()
    {
        priority_queue<node> que;
        memset(vis,0,sizeof(vis));
        node tmp,next;
        tmp.x = n;
        tmp.y = n;
        tmp.d = map[n][n];
        que.push(tmp);
        while(!que.empty())
        {
            tmp = que.top();
            que.pop();
            if(vis[tmp.x][tmp.y])
                continue; 
            vis[tmp.x][tmp.y] = 1;
            dis[tmp.x][tmp.y] = tmp.d; 
            for(int i = 0;i < 4;i++) {
                next.x = tmp.x+dir[i][0];
                next.y = tmp.y+dir[i][1];
                if(next.x<1||next.x>n||next.y<1||next.y>n||vis[next.x][next.y]) 
                    continue;
                next.d = tmp.d + map[next.x][next.y];
                que.push(next);
            }
        }
    }
    
    __int64 solve(int x,int y)
    {
        if(dp[x][y] != -1) return dp[x][y];
        else {
            node next;
            dp[x][y] = 0;
            for(int i = 0;i < 4;i++) {
                next.x = x+dir[i][0];
                next.y = y+dir[i][1];
                if(next.x<1||next.x>n||next.y<1||next.y>n)
                    continue;
                next.d = dis[next.x][next.y];
                if(next.d < dis[x][y]) 
                    dp[x][y]+=solve(next.x,next.y);
            }
            return dp[x][y];
        }
    }
    
    int main()
    {
        while(cin>>n)
        {
            memset(dp,-1,sizeof(dp));
            for(int i = 1;i <= n;i++)
                for(int j = 1;j <= n;j++)
                    cin>>map[i][j];
            dfs();
            /*测试最小距离 
            cout<<endl<<"~~~"<<endl;
            for(int i = 1;i <= n;i++)
                for(int j = 1;j <= n;j++){
                    cout<<dis[i][j]<<' ';
                    if(j == n)
                        cout<<endl;
                }
            */
            dp[n][n] = 1;
            cout<<solve(1,1)<<endl;
        }
        return 0;
    }
     
  • 相关阅读:
    ubuntu防火墙设置通过某端口
    pandas入门
    pyplot入门
    numpy教程
    跨域请求 spring boot
    spring boot 启动流程
    代理配置访问
    AOP,拦截器
    spring boot 启动不连接数据库
    Python 3.x 连接数据库(pymysql 方式)
  • 原文地址:https://www.cnblogs.com/immortal-worm/p/4984652.html
Copyright © 2011-2022 走看看