题目
测试得分: 100
主要算法 : 最短路-dijkstra,矩阵动规
题干:
矩阵中求左上角的点到右下角的点的距离,不能从下往上走
分析:
方案1(动规)
初步判定算法
对于这题,只能从上往下行走,对于到达每一个点的最优值,一定是从最上方下来的最优值,与左右两边最优值的比较,初步确定算法动态规划
分析初步算法
对于从两边来的最优值,只有左边目前是一路DP过来的最优值,而对于右边则是一个未知的,所以要进行两步DP,想从左边扫一遍左值,在从右扫一遍右值,上方,左右三者取一个min则是到这个点的最小花
方案2(最短路)
初步判定算法
典型的最短路问题
分析初步算法
将每一个节点,按照从上到下,从左到右的顺序编号,点数为N*M
建立到右边一个点,权值为右边那个点的权值的边,再建立到左边一个点,权值为左边那个点的权值的边,再建立到下边一个点,权值为下边那个点的权值的边。边数为3*M*N
跑一个最短路dijkstra,时间复杂度O(n*log(m)),对于这道题时间上是跑不过去的,可以得部分分
代码
#include<stdio.h>
#include<stdlib.h>
#define INF 2147483647
#define FORa(i,s,e) for(int i=s;i<=e;i++)
#define FORs(i,s,e) for(int i=s;i>=e;i--)
#define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++
#define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout);
using namespace std;
static char buf[1000000],*pa=buf,*pb=buf;
inline int read();
const int M=1000,N=1000;
struct Node{
int next,to,dis;
}edge[M*N*4];
bool bz[M*N];
int a[N+1][M+1];
int n,m,star,end,dis[M*N],head[M*N],num_edge,fdis[N+1][M+1];
inline int min(int fa,int fb){return fa<fb?fa:fb;}
void Add_edge(int from,int to,int d)
{
num_edge++,edge[num_edge]=(Node){head[from],to,d},head[from]=num_edge;
}
struct Que{
int u,dis;
bool operator < (const Que &q) const{
return dis>q.dis;
}
}q;
priority_queue<Que> que;
void Solve()
{
FORa(i,1,n) FORa(j,1,m) a[i][j]=read();
FORa(i,1,n) FORa(j,2,m) Add_edge((i-1)*m+j-1,(i-1)*m+j,a[i][j]),Add_edge((i-1)*m+j,(i-1)*m+j-1,a[i][j-1]);
FORa(j,1,m) FORa(i,2,n) Add_edge((i-2)*m+j,(i-1)*m+j,a[i][j]);
FORa(i,1,m*n) dis[i]=INF;
star=1,dis[star]=0,que.push((Que){star,0});
while(!que.empty())
{
q=que.top(),que.pop();
if(bz[q.u]) continue;
bz[q.u]=1;
for(int i=head[q.u];i;i=edge[i].next)
{
if(dis[edge[i].to]>dis[q.u]+edge[i].dis)
{
dis[edge[i].to]=dis[q.u]+edge[i].dis;
if(!bz[edge[i].to]) que.push((Que){edge[i].to,dis[edge[i].to]});
}
}
}
printf("%d",dis[m*n]);
}
void Solve2()
{
FORa(i,1,n) FORa(j,1,m) a[i][j]=read();
FORa(i,1,m) a[1][i]=a[1][i-1]+a[1][i],fdis[1][i]=a[1][i];
FORa(i,2,n)
{
FORa(j,1,m)
{
if(j>1) fdis[i][j]=a[i][j]+min(fdis[i-1][j],fdis[i][j-1]);
else fdis[i][j]=a[i][j]+fdis[i-1][j];
}
FORs(j,m,1)
{
if(j<=m-1) fdis[i][j]=min(fdis[i][j],a[i][j]+min(fdis[i-1][j],fdis[i][j+1]));
else fdis[i][j]=min(fdis[i][j],a[i][j]+fdis[i-1][j]);
}
}
printf("%d",fdis[n][m]);
}
int main()
{
File("castle");
n=read(),m=read();
if(n*m<=100) Solve();
else Solve2();
return 0;
}
inline int read()
{
register int x(0);register int f(1);register char c(gc);
while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
while(c>='0'&&c<='9') x=(x<<1)+ (x<<3)+(c^48),c=gc;
return x*f;
}
知识兔