hdu 5092 Seam Carving 简单DP ”水一炮试试“大法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5092
非常卡读题
题目中说可以八个方向地走,完全没有提及是从上往下的
需要从样例中猜测”可能只是从上往下“,然后根据现场的过题情况决定要不要水一发试试
对于”水一炮试试“,感觉一般适用于:
1.本题的其他做法未果/很难写,其他的题目没法出
2.码的成本不会很高
3.心态上,得之我幸,失之我命
(水不过的时候,再检查一下水的姿势有没有什么不妥,如果还是不行,就要勇敢地、果断地走出过不了题的不开心~)
所以真正的题意是
只能从上往下走,8方向相邻
求权值和最小的路径 输出路径
如果有多条路径同时满足则输出最右的一条
教科书例题级别的DP
#include <cstring> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <cstdio> #include <stack> #include <vector> #include <queue> #include <map> #include <set> using namespace std; const int maxn = 110; const int INF = 0x7fffffff; int a[maxn][maxn]; int dp[maxn][maxn]; int pre[maxn][maxn]; int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); int kase = 0; while(T--) { printf("Case %d\n", ++kase); int m, n; scanf("%d%d", &m, &n); for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) scanf("%d", &a[i][j]); for(int i = 1; i <= m; i++) dp[i][0] = dp[i][n+1] = INF; for(int j = 1; j <= n; j++) dp[1][j] = a[1][j]; for(int i = 2; i <= m; i++) { for(int j = 1; j <= n; j++) { if(dp[i-1][j-1] < dp[i-1][j] && dp[i-1][j-1] < dp[i-1][j+1]) //必须要严格小于才选最左边 { dp[i][j] = dp[i-1][j-1] + a[i][j]; pre[i][j] = j-1; } else if(dp[i-1][j] < dp[i-1][j+1]) { dp[i][j] = dp[i-1][j] + a[i][j]; pre[i][j] = j; } else { dp[i][j] = dp[i-1][j+1] + a[i][j]; pre[i][j] = j+1; } } } int minloc = 0; for(int i = 1; i <= n; i++) if(dp[m][i] <= dp[m][minloc]) minloc = i; stack<int> st; for(int i = m; i >= 1; i--) { st.push(minloc); if(i != 1) minloc = pre[i][minloc]; } for(int i = 0; i < m; i++) { printf("%d%c", st.top(), " \n"[i == m-1]); st.pop(); } } return 0; }