Code Jam 2010 Round 1A Problem B

Problem B. Make it Smooth

Problem

You have a one-dimensional array of N pixels. Each pixel has a value, represented by a number between 0 and 255, inclusive. The distance between two pixels is the absolute difference of their numbers.

You can perform each of the following operations zero or more times:

  1. With cost D, delete any pixel, so its original neighbors become neighboring pixels.
  2. With cost I, insert one pixel of any value into any position -- either between two existing pixels, or before the first pixel, or after the last pixel.
  3. You can change the value of any pixel. The cost is the absolute difference of the old value of the pixel and the new value of the pixel.

The array is smooth if any neighboring pixels have distance at most M. Find the minimum possible cost of a sequence of operations that makes the array smooth.

Note: The empty array -- the array containing no pixels -- is considered to be smooth.

Input

The first line of the input gives the number of test cases, TT test cases follow, each with two lines. The first line is in the form "D I M N", the next line contains N numbers ai: the values of the pixels from left to the right.

Output

For each test case, output one line containing "Case #x: y", where x is the case number (starting from 1), and y is the minimum cost to make the input array smooth.

Limits

All the numbers in the input are integers.
1 ≤ T ≤ 100
0 ≤ DIMai ≤ 255

Small dataset

1 ≤ N ≤ 3.

Large dataset

1 ≤ N ≤ 100.

Sample


Input 
 

Output 
 
2
6 6 2 3
1 7 5
100 1 5 3
1 50 7
Case #1: 4
Case #2: 17

Explanation

In Case #1, decreasing the 7 to 3 costs 4 and is the cheapest solution. In Case #2, deleting is extremely expensive; it's cheaper to insert elements so your final array looks like [1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 50, 45, 40, 35, 30, 25, 20, 15, 10, 7].

解题思路:

最近遇到的一些动态规划问题中感觉最难的一个,思考明白后让我对动态规划的理解更深刻了。思路是这个数组中的每个数字在最小代价时,不确定大小,但是在0-255范围内把每种不同组合的情况都考虑到,找出其中最小的代价。在找的过程中,可以先找数组前1个的最小代价,然后利用前1个的结论找前2个的最小代价,也就是用动态规划的思想递归求解。在定义数组a[N],存放输入的N个记录。定义dp[N+1][256],例如dp[i+1][j]的意义是,a的子数组a[0:i]中最后一个像素变为j时的最小代价。可能的情况有:

1. 删除a[i+1],那么cost=dp[i][j] + D,即a[i]变为j的代价加上删除a[i+1]代价。 

2.修改a[i+1]变为j,那么需要考虑a[i]不同情况,我们使用辅助变量k表示a[i]的不同情况,0<=k<=255。cost=dp[i][k]+insert_cost+move_cost,其中move_cost指的是将a[i+1]修改为j的代价,insert_cost指的是将k到j之间通过插入使之平滑的代价。

求出删除a[i+1]与k取不同值时修改a[i+1]的代价的最小值,即为a[i+1][j]的值。接下来只需要找出dp[N][0:255]中的最小值,即为答案。

	void run() {
		int COUNT = sc.nextInt();
		for (int c = 0; c < COUNT; c++) {
			int D = sc.nextInt();
			int I = sc.nextInt();
			int M = sc.nextInt();
			int N = sc.nextInt();
			int[] a = new int[N];
			for (int i = 0; i < N; i++) {
				a[i] = sc.nextInt();
			}
			int[][] dp = new int[N + 1][256];
			for (int i = 0; i < N; i++) {
				for (int j = 0; j < 256; j++) {
					int tmp = dp[i][j] + D;
					if (M == 0) {
						tmp = min(tmp, dp[i][j] + abs(a[i] - j));
					} else {
						for (int k = 0; k < j; k++) {
							int diff = abs(j - k);
							int insert = max(diff - 1, 0) / M;
							int cost = dp[i][k] + insert * I + abs(a[i] - j);
							if (cost < tmp)
								tmp = cost;
						}
					}
					dp[i + 1][j] = tmp;
				}
			}
			int min = Integer.MAX_VALUE;
			for (int i = 0; i < 256; i++)
				min = min(min, dp[N][i]);
			System.out.println(String.format("Case #%d: %d", c + 1, min));
		}
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值