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 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
 

题意:给一个N*M的矩阵,让你用一条线 从第1行连到第N行(每行仅仅能选一个元素),要求这条线所经过的元素之和最小。 
有下面规定——
1,若你选择了位置(i,j)的元素,那么下一行的元素你仅仅能选择(i+1。j-1)、(i+1。j)、(i+1,j+1)三个之中的一个(当然边界仅仅能选两个)。

2,若能够找到多条  路径上元素之和最小 的线,那么你要优先选择最右边的线。
3。最后从第一行開始 输出线上元素的纵坐标。



思路:就是树塔变形题嘛。在自底往上推最优值的过程中。设置数组记录前驱,最后选择最右边的线输出路径就可以。因为题目没有说清楚(可能是我英语太渣)在找线的过程中是否要优先选择最右边的元素,所以我在DP过程中选择从左到右一直更新前驱。


队友说DP难,没心情深挖。

没办法,仅仅好主修图论 + DP。 其他仅仅能辅修了o(╯□╰)o


AC代码:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node
{
int pos;
};
Node mark[110][110];//标记该位置是由 哪一位置得到的(自底往上)
int dp[110][110];
int N, M;
int k = 1;
void getMap()
{
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= M; j++)
scanf("%d", &dp[i][j]);
}
}
void solve()
{
int t;
for(int i = N-1; i >= 1; i--)
{
for(int j = 1; j <= M; j++)
{
if(j == 1)
{
t = min(dp[i+1][j], dp[i+1][j+1]);//找到最小值
dp[i][j] += t;
//从左到右更新 前驱
if(t == dp[i+1][j])
mark[i][j].pos = j;
if(t == dp[i+1][j+1])
mark[i][j].pos = j + 1;
}
else if(j == M)
{
t = min(dp[i+1][j], dp[i+1][j-1]);
dp[i][j] += t;
if(t == dp[i+1][j-1])
mark[i][j].pos = j - 1;
if(t == dp[i+1][j])
mark[i][j].pos = j;
}
else
{
int t = min(dp[i+1][j], min(dp[i+1][j-1], dp[i+1][j+1]));
dp[i][j] += t;
if(t == dp[i+1][j-1])
mark[i][j].pos = j-1;
if(t == dp[i+1][j])
mark[i][j].pos= j;
if(t == dp[i+1][j+1])
mark[i][j].pos = j+1;
}
}
}
int sx = 1;
int Max = dp[1][1];
for(int i = 2; i <= M; i++)
{
if(Max >= dp[1][i])//优先选择最右边的线
{
Max = dp[1][i];
sx = i;
}
}
printf("Case %d\n", k++);
printf("%d", sx);
int row = 1, cul = sx;//行号 列号
while(1)
{
if(row == N) break;
cul = mark[row][cul].pos;//下一列号
printf(" %d", cul);
row++;
}
printf("\n");
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &N, &M);
getMap();
solve();
}
return 0;
}

hdoj 5092 Seam Carving 【树塔DP变形 + 路径输出】 【简单题】的更多相关文章

  1. 递推DP HDOJ 5092 Seam Carving

    题目传送门 /* 题意:从上到下,找最短路径,并输出路径 DP:类似数塔问题,上一行的三个方向更新dp,路径输出是关键 */ #include <cstdio> #include < ...

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

    题意: 给一个m*n的矩阵,每格上有一个数. 找从第1行到第m行的一条路径,使得这条路径上的数之和最小. 路径必须满足相邻两行所选的两个数的纵坐标相邻(即一个格子必须是另一个格子的周围八个格子中的一个 ...

  3. HDU 5092 Seam Carving (dp)

    题意,给一个数字矩阵,要求从上往下的一条路径,使这条路径上数字之和最小,如有多条输出最靠右的一条. 数字三角形打印路径... 一般打印路径有两种选择,一是转移的时候加以记录,二是通过检查dp值回溯. ...

  4. hdu 5092 Seam Carving

    这道题 我没看出来 他只可以往下走,我看到的 8-connected :所以今天写一下如果是 8-connected 怎么解: 其实说白了这个就是从上到下走一条线到达最后一行的距离最小: 从Map[a ...

  5. uva 10131 Is Bigger Smarter ? (简单dp 最长上升子序列变形 路径输出)

    题目链接 题意:有好多行,每行两个数字,代表大象的体重和智商,求大象体重越来越大,智商越来越低的最长序列,并输出. 思路:先排一下序,再按照最长上升子序列计算就行. 还有注意输入, 刚开始我是这样输入 ...

  6. 【DP系列学习一】简单题:kickstart2017 B.vote

    https://code.google.com/codejam/contest/6304486/dashboard#s=p1 这是一道简单的dp,dp[i][j]代表A的voter为i,B的voter ...

  7. ZOJ-1456 Minimum Transport Cost---Floyd变形+路径输出字典序最小

    题目链接: https://vjudge.net/problem/ZOJ-1456 题目大意: Spring国家有N个城市,每队城市之间也许有运输路线,也可能没有.现在有一些货物要从一个城市运到另一个 ...

  8. 【JZOJ4746】【NOIP2016提高A组模拟9.3】树塔狂想曲

    题目描述 相信大家都在长训班学过树塔问题,题目很简单求最大化一个三角形数塔从上往下走的路径和.走的规则是:(i,j)号点只能走向(i+1,j)或者(i+1,j+1).如下图是一个数塔,映射到该数塔上行 ...

  9. HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)

    Seam Carving DescriptionFish likes to take photo with his friends. Several days ago, he found that s ...

随机推荐

  1. c25---条件编译

    // // main.c // 条件编译(宏定义是简单的替换,要给参数和结果都加括号) #include <stdio.h> #define SCORE 90 #define DEBUG ...

  2. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog]

    Could not load file or assembly 'System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31 ...

  3. hdoj--1068--Girls and Boys(最大独立集)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. findContours 轮廓查找

    物体的轮廓勾勒出了物体的整体形状,物体形状的边界像素一起组合成了轮廓. 灰度图像边界的明显特征是边界两侧灰度级的突变,根据这个特征,使用Sobel.拉普拉斯或Canny之类的边缘检测算子可以有效的检测 ...

  5. gdb的使用(转)

    gdb使用 转自清华大学操作系统实验指导书 gdb 是功能强大的调试程序,可完成如下的调试任务: 设置断点 监视程序变量的值 程序的单步(step in/step over)执行 显示/修改变量的值 ...

  6. EOJ 2844 排序去重

    有 n 个 1 到 1000 之间的整数 (1≤n≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉.然后再按照指定的排序方式把这些数排序. Input 第 1 行为字母 A 或 D,A ...

  7. C-数据和C

    1.常量与变量数据 有些数据在程序使用之前预先设定,并在整个运行过程中没有变化,叫做常量.另外的数据在程序运行过程中可能变化或被赋值,叫做变量. 2.数据类型关键字 对于变量,编译器通过声明语句中指定 ...

  8. JUC集合-BlockingQueue

    BlockingQueue 阻塞队列,支持两个附加操作. 1,在队列为空时,获取元素的线程会等待对列变为非空. 2,在队列为满时,存储元素的线程会等待对列可用. 使用场景: 生产者往对列里添加元素 消 ...

  9. Struts2学习笔记 - Part.02

    ================Struts2的国际化================程序国际化: 程序可以根据极其所在的国家.语言环境,自动显示当前国家.语言的内容国际化的本质是:查找.替换国际化的 ...

  10. Apex语言(二)变量与常量

    1.变量 凡是交给计算运算(处理)的数据就是变量,用来保存参加运算的数据和计算结果. 变量由变量名来标识. 变量名由字母数字和下划线组成,不能以数字开头. [正确]number,number1,num ...