hdu5092 dp(递推)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5092
题意:给一个m*n的矩阵,找到一个纵向的"线"使得线上的和最小并输出这条线,线能向8个方向
延伸,要求找的是纵向的一条线(每一行各取一个点连成一线) ,输出路径,若有多条路径,输出最
靠右的。
注意!! 最靠右的意思是,从上往下最靠右的,是连成一条线上字典序是最大的!! 字典序!!! eg(3,1,3)<(3,2,1)
好不容易自己想出来一道题 还因为字典序没搞懂一直WA。
字典序最大那么久要从下往上dp,找最小值里面最右面的,记录路径。这样就比较容易理解了。
具体见代码:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int mp[105][105]; int dp[105][105],path[105][105]; int d[105]; int m,n; int main() { int T; scanf("%d",&T); for(int p=1; p<=T; p++) { scanf("%d%d",&m,&n); for(int i=1; i<=m; i++) for(int j=1; j<=n; j++) scanf("%d",&mp[i][j]); memset(dp,0,sizeof(dp)); memset(path,0,sizeof(path)); for(int i=1; i<=n; i++) dp[m][i]=mp[m][i]; for(int i=1; i<=n; i++) for(int i=m-1; i>=1; i--) { int maxx; for(int j=1; j<=n; j++) { if(j==1) { maxx=dp[i+1][j],path[i][j]=j; if(dp[i+1][j+1]<=dp[i+1][j]) maxx=dp[i+1][j+1],path[i][j]=j+1; } else if(j==n) { maxx=dp[i+1][j-1],path[i][j]=j-1; if(dp[i+1][j]<=dp[i+1][j-1]) maxx=dp[i+1][j],path[i][j]=j; } else { maxx=dp[i+1][j-1],path[i][j]=j-1; if(dp[i+1][j]<=maxx) maxx=dp[i+1][j],path[i][j]=j; if(dp[i+1][j+1]<=maxx) maxx=dp[i+1][j+1],path[i][j]=j+1; } dp[i][j]=mp[i][j]+maxx; } } int minn=dp[1][1],k=1; for(int i=2; i<=n; i++) if(dp[1][i]<=minn) minn=dp[1][i],k=i; printf("Case %d\n",p); memset(d,0,sizeof(d)); int pt=k,t=1; d[1]=k; for(int i=1; i<m; i++) { pt=path[i][pt]; d[++t]=pt; } for(int i=1; i<t; i++) printf("%d ",d[i]); printf("%d\n",d[t]); } return 0; }

浙公网安备 33010602011771号