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.

hdu 5092 Seam Carving dp+记录路径_第1张图片
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

你可能感兴趣的:(dp)