简单的dp
题目大意是给一个网格
然后有一些近路
求从(0,0)到(M,N)的最短距离
-------------------------------解释题目的分割线----------------------
嘛
很显然每个非边界的点可以从下面的点或者左边的点走过来
特别的 如果有近路 还要考虑近路
在这几个情况中取得最小值
那么有状态转移式 dp[i][j]=min(dp[i-1][j],dp[i][j-1])+100;
if(存在近路) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+根号二*100);
(注意边界的处理
------------------------------我也不知道我是什么的分界线---------
要是说坑点的话 四舍五入应该算一个
其他的就不知道了
一次过~
#include<cstdio>
#include<cstring>
#include<algorithm>
//#define DEBUG
using namespace std;
const double INF=10000.0;
bool xy[1005][1005];
double dp[1005][1005];
int main(){
int n,m;
double two=1.414213;
while(~scanf("%d %d",&m,&n)){
memset(xy,0,sizeof(xy));
memset(dp,0,sizeof(dp));
dp[0][0]=0;
int k;
scanf("%d",&k);
int a,b;
while(k--){
scanf("%d %d",&a,&b);
xy[a][b]=true;
}
for(int i=0;i<=m;i++)
for(int j=0;j<=n;j++){
if(i==0 || j==0){
if(j!=0)
dp[i][j]=dp[i][j-1]+1;
if(i!=0)
dp[i][j]=dp[i-1][j]+1;
if(i==0 && j==0)
dp[i][j]=0;
}
else{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+1;
if(xy[i][j]) dp[i][j]=min(dp[i][j],dp[i-1][j-1]+two);
}
}
#ifdef DEBUG
for(int i=m;i>=0;i--)
for(int j=0;j<=n;j++)
printf(j<n?"%.2lf ":"%.2lf\n",dp[i][j]);
#endif // DEBUG
int ans=dp[m][n]*100+0.5;
printf("%d\n",ans);
}
return 0;
}