优先队列+记忆化搜索

来源:互联网 发布:旅游市场调查数据 编辑:程序博客网 时间:2024/06/14 10:00

算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,以后再次遇到这个状态的时候,就不必重新求解了。这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。上传/更换附件动态规划的另一种实现形式——记忆化搜索的应用1.记忆化搜索的思想: 记忆化搜索的思想是,在搜索过程中,会有很多重复计算,如果我们能记录一些状态的答案,就可以减少重复搜索量2、记忆化搜索的适用范围:根据记忆化搜索的思想,它是解决重复计算,而不是重复生成,也就是说,这些搜索必须是在搜索扩展路径的过程中分步计算的题目,也就是“搜索答案与路径相关”的题目,而不能是搜索一个路径之后才能进行计算的题目,必须要分步计算,并且搜索过程中,一个搜索结果必须可以建立在同类型问题的结果上,也就是类似于动态规划解决的那种。也就是说,他的问题表达,不是单纯生成一个走步方案,而是生成一个走步方案的代价等,而且每走一步,在搜索树/图中生成一个新状态,都可以精确计算出到此为止的费用,也就是,可以分步计算,这样才可以套用已经得到的答案3、记忆化搜索的核心实现a. 首先,要通过一个表记录已经存储下的搜索结果,一般用哈希表实 b.状态表示,由于是要用哈希表实现,所以状态最好可以用数字表示,常用的方法是把一个状态连写成一个p进制数字,然后把这个数字对应的十进制数字作为状态c.在每一状态搜索的开始,高效的使用哈希表搜索这个状态是否出现过,如果已经做过,直接调用答案,回溯d.如果没有,则按正常方法搜索4、记忆化搜索是类似于动态规划的,不同的是,它是倒做的“递归式动态规划

点击打开链接

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
31 2 31 2 31 2 331 1 11 1 11 1 1
 

Sample Output
16

解题思路:首先理解清楚题意:LL这个人要从左上角到右下角,要求路径中存在a,b两个点,且从b到右下角的距离比任何 一条从A到右下角的距离都短,即b到终点的距离大于a到终点的最小距离。所以我们从终点开始,计算它到每个点的最短距离 然后再深搜一次找符合题意的路径数

#include <iostream>#include <bits/stdc++.h>using namespace std;struct Node//定义优先队列{    int x,y,s;    bool friend operator < (Node a,Node b)    {        return a.s>b.s;    }};int n,vis[55][55];long long int dist[55][55],Map[55][55],dp[55][55];//dist保存每个点到终点的最短路径,dp保存符合题意的路径数int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};void Bfs(){    memset(vis,0,sizeof(vis));    priority_queue<Node> Q;    Node cur,next;    cur.x=n-1;cur.y=n-1;cur.s=Map[cur.x][cur.y];    Q.push(cur);    vis[n-1][n-1]=1;    while(!Q.empty())    {        cur=Q.top();        Q.pop();        dist[cur.x][cur.y]=cur.s;        for(int i=0;i<4;i++)        {            next.x=cur.x+dir[i][0];            next.y=cur.y+dir[i][1];            if(next.x>=0&&next.x<n&&next.y>=0&&next.y<n&&vis[next.x][next.y]==0)            {                next.s=Map[next.x][next.y]+cur.s;                vis[next.x][next.y]=1;                Q.push(next);            }        }    }}long long dfs(int x,int y){    if(dp[x][y]) return dp[x][y];    if(x == n-1 &&y==n-1) return 1;    for(int i=0; i<4; i++)    {        int x1=x+dir[i][0];        int y1=y+dir[i][1];        if(x1<0||x1>=n||y1<0||y1>=n||dist[x][y]<=dist[x1][y1])            continue;        dp[x][y]+=dfs(x1,y1);    }    return dp[x][y];}int main(){    while(cin>>n)    {memset(dp,0,sizeof(dp));        for(int i=0;i<n;i++)        {            for(int j=0;j<n;j++)            {                cin>>Map[i][j];            }        }        Bfs();        cout<<dfs(0,0)<<endl;    }    return 0;}

题意:给你一个图,找最短路。但是有个非一般的的条件:如果a,b之间有路,

且你选择要走这条路,那么必须保证b到终点的所有路都小于a到终点的一条路。

问满足这样的路径条数有多少?

解题思路:

1.1为起点,2为终点,因为要走ab路时,必须保证那个条件,所以从终点开始使用单源最短路Dijkstra算法,就得到了最短的一条路,作为找路的最低限度。

2.然后深搜每条路,看看满足题意的路径有多少条。当然,这个需要从起点开始搜,因为dis[i]数组中保存的都是该点到终点的最短距离。

3.这样搜索之后,dp[1]就是从起点到终点所有满足题意的路径的条数。*/

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int inf = 999999999;int map[1005][1005];int dis[1005],vis[1005];int path[1005];int n,m;void Dijkstra(int src){    int i,j,minn,pos;    memset(vis,0,sizeof(vis));    for(i = 0; i<=n; i++)        dis[i] = map[src][i];    dis[src] = 0;    vis[src] = 1;    for(i = 1; i<=n; i++)    {        minn = inf;        pos = 0;        for(j = 1; j<=n; j++)        {            if(minn>dis[j] && !vis[j])               {                   minn = dis[ j];pos = j;               }        }        vis[pos] = 1;        for(j = 1; j<=n; j++)            if(dis[j]>dis[pos]+map[pos][j] && !vis[j])                dis[j] = dis[pos]+map[pos][j];    }}///用path数组来保存符合条件的路径数int DFS(int src){    if(path[src] !=-1)        return path[src];    if(src == 2)///如果找到终点就返回1,代表有一条路        return 1;    //path[src] = 0;    for(int i = 1; i<=n; i++)    {        if(dis[i]<dis[src] && map[i][src]!=inf)///i相当于b,src相当于a,如果a能到b且从b到他家的最短路小于从a到他家的最短路            path[src]+=DFS(i);    }    return path[src];}int main(){    int i,j,x,y,z;    while(~scanf("%d",&n),n)    {        scanf("%d",&m);        for(i = 0; i<=n; i++)        {            for(j = 0; j<=n; j++)                map[i][j] = inf;            map[i][i] = 0;        }        for(i = 0; i<m; i++)        {            scanf("%d%d%d",&x,&y,&z);            map[x][y] = map[y][x] = z;        }        Dijkstra(2);        memset(path,-1,sizeof(path));        printf("%d\n",DFS(1));    }  




原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 暗影格斗3闪退怎么办 暗影格斗3文档被删怎么办 dnf手残党偷学技能学不了怎么办 打篮球没热身膝盖酸痛是怎么办 无线路由器lan口少怎么办? 电脑ip设置乱了怎么办 监控拍我我偷钱怎么办 网吧上网密码忘记了怎么办 比熊犬晚上叫怎么办 刚买的狗一直叫怎么办 酒驾罚款2年没交怎么办 法院判罚款没有钱怎么办 有人朝你吐口水怎么办 孕妇用了六神花露水怎么办 出车祸人不赔钱怎么办 交通事故对方保险不签字怎么办 肇事车主联系不上怎么办 商标被别人申请无效宣告怎么办 淘宝上传宝贝没有品牌怎么办 萌虎白卡借款2000逾期了怎么办 最里面的牙齿烂了怎么办 金龙沉底不游怎么办 龙鱼尾巴烂了怎么办 微博忘了登录名和密码怎么办 新浪微博密码忘了怎么办 vivo手机用户密码忘了怎么办 微博登录名忘记了怎么办 微信忘记密码钱怎么办 微信密码申诉失败怎么办 微博密码被盗了怎么办 对公密码器丢了怎么办 手机qq忘记旧密码怎么办 qq旧密码忘记了怎么办 微博账户密码忘记了怎么办 三星盖乐世s3忘记密码了怎么办 微博登录密码忘记了怎么办 助学贷款密码忘了怎么办 助学贷款的密码忘了怎么办 助学贷款登录密码忘了怎么办 抖音换了手机登不了怎么办 微信忘记密码申诉失败怎么办