题目大意:要求从左边到右边(注意第1行和最后一行相邻),即:从第1列到最后一列即可,共有三种走法,求最小的代价及打印行号。
三种走法,
Sample Input
5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 8 6 4 5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 1 2 3 2 2 9 10 9 10
Sample Output
1 2 3 4 4 5 16 1 2 1 5 4 5 11 1 1 19
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 222 #define inf 1<<30 int map[MAXN][MAXN]; int dp[MAXN][MAXN]; int n,m,len; int path[MAXN]; int dfs(int x, int y) { if(dp[x][y]!=inf) return dp[x][y]; if(y==m-1) return dp[x][y]=map[x][y]; int ans=min(min(dfs((x-1+n)%n,y+1),dfs(x,y+1)),dfs((x+1)%n,y+1)); return dp[x][y]=ans+map[x][y]; } void Solve(int x, int y) { path[len++]=x; if(y==m-1)return ; int x1=(x-1+n)%n, x2=x, x3=(x+1)%n; for(int i=0;i<n;i++) { if(dp[x][y]==dp[i][y+1]+map[x][y]&&(i==x1||i==x2||i==x3)) { Solve(i,y+1); return ; } } } int main() { while(~scanf("%d%d",&n,&m)) { memset(dp,0,sizeof(dp)); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) dp[i][j]=inf; for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&map[i][j]); int ans=inf,pos; for(int i=0;i<n;i++) { if(dfs(i,0)<ans) { ans=dp[i][0]; pos=i; } } len=0; Solve(pos,0);//从第一列的第pos行往后找路径(dp[pos][0]即为最小值) printf("%d",path[0]+1); for(int i=1;i<len;i++) printf(" %d",path[i]+1); printf(" %d ",ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。