HDU 1428 bfs(优先队列计算最短距离) dfs(记忆化搜索)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

struct node{
    int x,y,cost;
    friend bool operator < (node a,node b){
        return a.cost > b.cost;
    }
};

int n;
int graph[55][55];
bool vis[55][55];
long long dp[55][55];
int dist[55][55];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};

void bfs(){
    priority_queue<node> q;
    memset(vis,false,sizeof(vis));
    node cur,next;
    cur.x = n;
    cur.y = n;
    cur.cost = graph[n][n];
    q.push(cur);
    while(!q.empty()){
        cur = q.top();   //当前距离最小的一个点
        q.pop();
        if(vis[cur.x][cur.y]) continue;  //只有第一次出队的点才是最小值的点
        vis[cur.x][cur.y] = true;
        dist[cur.x][cur.y] = cur.cost;
        for(int i=0;i<4;i++){
            next.x = cur.x+dx[i];
            next.y = cur.y+dy[i];
            if(next.x>=1 && next.x<=n && next.y>=1 && next.y<=n && !vis[next.x][next.y]){
                next.cost = cur.cost+graph[next.x][next.y];
                q.push(next);
            }
        }
    }
}

long long dfs(int x,int y){
    if(dp[x][y]!=-1) return dp[x][y];
    dp[x][y] = 0;
    for(int i=0;i<4;i++){
        int xx = x+dx[i];
        int yy = y+dy[i];
        if(xx>=1 && xx<=n && yy>=1 && yy<=n){
            if(dist[xx][yy] < dist[x][y])  //约束条件
                dp[x][y] += dfs(xx,yy);
        }
    }
    return dp[x][y];
}


int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&graph[i][j]);
        bfs();  //先用bfs计算距离,由于每个点的cost不是1,所以需要使用优先队列
        memset(dp,-1,sizeof(dp));
        dp[n][n] = 1;
        printf("%lld\n",dfs(1,1));   //得到距离之后,使用dfs的记忆化搜索,得到解的个数
        //在生成解的时候,需要设定约束条件
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42246923/article/details/80760695
今日推荐