做了杭电1428 这道搜索题,记忆化搜索就是 搜索的形式+动态规划的思想。。
之所以要记忆化,是因为相互之间的拓扑关系较复杂,不是那种严格限制只能向左向右走的。所以用一个dp数组记住。。
下面解释下题意: 从(1,1)走到(n,n)每次可以上,下,左,右四个方向。但是有前提,前提是这样的:假如(1,1)到(n,n)最短耗时为time,那么你接下来走到(x,y)必须保证(x,y)到(n,n)的最短耗时小于time.
所以先以(n,n)为源点,用bfs求出到每一点的最短距离,然后再dfs记忆化搜索。。
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int x,y,t;
friend bool operator <(node n1,node n2)
{
return n1.t>n2.t;
}
};
int s[64][64],visit[64][64],dp[64][64],n;
int xx[]={1,-1,0,0};
int yy[]={0,0,1,-1};
bool ok(node p)
{
return p.x>=1&&p.x<=n&&p.y>=1&&p.y<=n;
}
bool is_ok(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=n;
}
void bfs(int x,int y)
{
priority_queue<node> que;
node cur,next;
cur.x=x;
cur.y=y;
cur.t=s[x][y];
visit[x][y]=1;
que.push(cur);
while(!que.empty())
{
cur=que.top();
que.pop();
for(int i=0;i<4;i++)
{
next.x=cur.x+xx[i];
next.y=cur.y+yy[i];
if(ok(next)&&!visit[next.x][next.y])
{
visit[next.x][next.y]=1;
s[next.x][next.y]+=cur.t;
next.t=s[next.x][next.y];
que.push(next);
}
}
}
}
int dfs(int x,int y)
{
if(dp[x][y])return dp[x][y];
for(int i=0;i<4;i++)
{
int tx=x+xx[i];
int ty=y+yy[i];
if(s[x][y]>s[tx][ty]&&is_ok(tx,ty))
dp[x][y]=dfs(tx,ty);
}
return dp[x][y];
}
int main()
{
while(cin>>n)
{
memset(visit,0,sizeof(visit));
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>s[i][j];
bfs(n,n);
dp[n][n]=1;
cout<<dfs(1,1)<<endl;
}
return 0;
}