hdu 5092 Seam Carving dp+记录路径

Seam Carving

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 605    Accepted Submission(s): 253

Problem Description

Fish likes to take photo with his friends. Several days ago, he found that some pictures of him were damaged. The trouble is that there are some seams across the pictures. So he tried to repair these pictures. He scanned these pictures and stored them in his
computer. He knew it is an effective way to carve the seams of the images He only knew that there is optical energy in every pixel. He learns the following principle of seam carving. Here seam carving refers to delete through horizontal or vertical line of
pixels across the whole image to achieve image scaling effect. In order to maintain the characteristics of the image pixels to delete the importance of the image lines must be weakest. The importance of the pixel lines is determined in accordance with the
type of scene images of different energy content. That is, the place with the more energy and the richer texture of the image should be retained. So the horizontal and vertical lines having the lowest energy are the object of inspection. By constantly deleting
the low-energy line it can repair the image as the original scene.

For an original image G of m*n, where m and n are the row and column of the image respectively. Fish obtained the corresponding energy matrix A. He knew every time a seam with the lowest energy should be carved. That is, the line with the lowest sum of energy
passing through the pixels along the line, which is a 8-connected path vertically or horizontally.

Here your task is to carve a pixel from the first row to the final row along the seam. We call such seam a vertical seam.

Input

There several test cases. The first line of the input is an integer T, which is the number of test cases, 0<T<=30. Each case begins with two integers m, n, which are the row and column of the energy matrix of an image, (0<m,n<=100). Then on the next m line,
there n integers.

Output

For each test case, print “Case #” on the first line, where # is the order number of the test case (starting with 1). Then print the column numbers of the energy matrix from the top to the bottom on the second line. If there are more than one such seams, just
print the column number of the rightmost seam.

Sample Input

2
4 3
55 32 75
17 69 73
54 81 63
47 5 45
6 6
51 57 49 65 50 74
33 16 62 68 48 61
2 49 76 33 32 78
23 68 62 37 69 39
68 59 77 77 96 59
31 88 63 79 32 34

Sample Output

Case 1
2 1 1 2
Case 2
3 2 1 1 2 1

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5092

题意:求一条路线,从矩阵的顶到矩阵的底,只能走到左下方,正下方,右下方。问总和最小的走法。  输出从第一行到最后一行每行走的点的列标。要求相等的情况下,选最右边的路线。

做法:dp就好了,读懂题就不难了。因为路径从第一行开始的,所以我把输入的矩阵上下颠倒了。

然后除了第一行的的 dp值 赋值成输入的以外,都初始化为INF。  然后转移过来后,如果从右边,就dir[i][r]=1, 中间0 ,左边-1。注意要先更新右边的,因为要选最右边的路线。

然后dp好了从最后一行 中选出最小的,相等的话取最右边的,然后遍历到第一行,每次根据dir,改变列号,输出就好了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map> 

#define INF 999999999999;
__int64 num[110][110];
__int64 dp[110][110];
__int64 dir[110][110];
int main()
{
    __int64 t;
	__int64 n,m;
	__int64 cas=1;
	scanf("%I64d",&t);
    while(t--)   //k 个配
    {
		scanf("%I64d%I64d",&n,&m);
		for(__int64 i=1;i<=n;i++)
		{
			for(__int64 j=1;j<=m;j++)
			{
				scanf("%I64d",&num[n-i+1][j]);
			}
		}

		for(__int64 i=0;i<=n;i++)
		{
			for(__int64 j=0;j<=m+1;j++)
			{
				dp[i][j]=INF;
			}
		}

		for(__int64 j=1;j<=m;j++)
			dp[1][j]=num[1][j];
		for(__int64 i=2;i<=n;i++)
		{
			for(__int64 j=1;j<=m;j++)
			{
				__int64 l=dp[i-1][j-1];
				__int64 mid=dp[i-1][j];
				__int64 r=dp[i-1][j+1];
				if(r+num[i][j]<dp[i][j])
				{
					dp[i][j]=r+num[i][j];
					dir[i][j]=1;
				}

				if(mid+num[i][j]<dp[i][j])
				{
					dp[i][j]=mid+num[i][j];
					dir[i][j]=0;
				}

				if(l+num[i][j]<dp[i][j])
				{
					dp[i][j]=l+num[i][j];
					dir[i][j]=-1;
				}
			}
		}

		__int64 minn=INF;
		__int64 id=-1;
		for(__int64 j=m;j>=1;j--)
		{
			if(dp[n][j]<minn)
			{
				minn=dp[n][j];
				id=j;
			}
		}
		printf("Case %I64d\n",cas++);
		printf("%I64d",id);

		for(__int64 i=n;i>=2;i--)
		{
			id+=dir[i][id];

			printf(" %I64d",id);
		}
		puts("");
    }
    return 0;
}
 

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5092

时间: 2024-08-05 11:14:02

hdu 5092 Seam Carving dp+记录路径的相关文章

hdu 5092 Seam Carving(DP+记录路径)

Seam Carving Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 119    Accepted Submission(s): 69 Problem Description Fish likes to take photo with his friends. Several days ago, he found that som

hdu 5092 Seam Carving 简单DP ”水一炮试试“大法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5092 非常卡读题 题目中说可以八个方向地走,完全没有提及是从上往下的 需要从样例中猜测”可能只是从上往下“,然后根据现场的过题情况决定要不要水一发试试 对于”水一炮试试“,感觉一般适用于: 1.本题的其他做法未果/很难写,其他的题目没法出 2.码的成本不会很高 3.心态上,得之我幸,失之我命 (水不过的时候,再检查一下水的姿势有没有什么不妥,如果还是不行,就要勇敢地.果断地走出过不了题的不开心-)

hdu 5092 Seam Carving (简单数塔DP,题没读懂,,不过可以分析样例)

题意: 给一个m*n的矩阵,每格上有一个数. 找从第1行到第m行的一条路径,使得这条路径上的数之和最小. 路径必须满足相邻两行所选的两个数的纵坐标相邻(即一个格子必须是另一个格子的周围八个格子中的一个) 输出每一行取的数的列值.  若有多个答案,则路径要求尽量靠右. 思路: 简单数塔DP.题比较不好读,不过可以分析样例. 代码: int T,m,n; int a[105][105], f[105][105]; int path[105]; int main(){ cin>>T; rep(t,1

hdu 5092 Seam Carving

这道题 我没看出来 他只可以往下走,我看到的 8-connected :所以今天写一下如果是 8-connected 怎么解: 其实说白了这个就是从上到下走一条线到达最后一行的距离最小: 从Map[a][b] 到Map[a][b+1] 的距离是Map[a][b+1] 以此类推:建图即可: 然后在加一个点0,和n+m+1 点这样在建立一下从  0 点到第一行的边,和最后一行到(n+m+1) 的边 求一个从0 到(n+m+1) 的最短路径就好了, 怎么维护最右侧?:  Dijkstra  有 队列优

递推DP HDOJ 5092 Seam Carving

题目传送门 1 /* 2 题意:从上到下,找最短路径,并输出路径 3 DP:类似数塔问题,上一行的三个方向更新dp,路径输出是关键 4 */ 5 #include <cstdio> 6 #include <algorithm> 7 #include <iostream> 8 #include <cstring> 9 #include <cmath> 10 #include <string> 11 #include <vector

POJ 1141 Brackets Sequence (区间dp 记录路径)

题目大意: 给出一种不合法的括号序列,要求构造出一种合法的序列,使得填充的括号最少. 思路分析: 如果只要求输出最少的匹配括号的数量,那么就是简单的区间dp dp[i][j]表示 i - j 之间已经合法了最少添加的括号数. 转移 就是 dp[i] [j] = min  (dp[i+1][j]+1 , dp[ i+ 1] [ k -1 ] + dp[k+1] [j] (i k 位置的括号匹配)) 其次我们要记录路径,你发现  如果 dp [i] [j] 是由 dp [i+1] [j] 转移过来的

hdoj 5092 Seam Carving 【树塔DP变形 + 路径输出】 【简单题】

Seam Carving Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 956    Accepted Submission(s): 382 Problem Description Fish likes to take photo with his friends. Several days ago, he found that so

URAL 1244 Gentlement DP +记录路径 好题

1244. Gentlemen Time limit: 0.5 secondMemory limit: 64 MB Let's remember one old joke: Once a gentleman said to another gentleman:— What if we play cards?— You know, I haven't played cards for ten years…— And I haven't played for fifteen years…So, li

[AC自动机+dp+记录路径] hdu 2825 Ring

题意: 给N个长度,M个单词,每个单词有权值 输出长度不大于N的权值和最大的单词 代价相同输出长度短的,长度相同输出字典序最小 思路: 开一个字符串数组,暴力存储每个节点的单词! 其他思路和dp都一样 注意:如果和为零的话输出空串. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue"