码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4362 Dragon Ball(维护最小值DP优化)

时间:2015-08-08 06:43:55      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:hdu



题意: 在连续的 n 秒中,每秒会出现 m 个龙珠,出现之后会立即消失,知道了第一秒所在的位置,每从一个位置移动到另一个位置的时候,消耗的价值为 abs(i-j), 知道了次出现的龙珠的价值,问 n 秒之后得到的最大价值是多少。

思路:这道题朴素的做法时间复杂度为O(n*n*m)勉强可以水过去,正解应该是用单调队列的思路维护最小值优化。

由状态转移方程dp[i][j] = min{ dp[i-1][k] + abs(pos[i-1][k]-pos[i][j]) } + cost[i][j]

可以推出dp[i][j]+pos[i][j]+cost[i][j] = min(dp[i-1][k]+pos[i-1][k]) (当pos[i-1][k]>pos[i][j]))

所以可以按位置排序后维护dp[i-1][k]+pos[i-1][k])的最小值。

#include<cstdio>  
#include<cstring>  
#include<cmath>  
#include<cstdlib>  
#include<iostream>  
#include<algorithm>  
#include<vector>  
#include<map>  
#include<queue>  
#include<stack> 
#include<string>
#include<map> 
#include<set>
#define eps 1e-6 
#define LL long long  
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000") 
using namespace std;  

const LL INF = 1000000000000000;
int n, m;
LL x;
struct Period {
	LL pos, e, dp;
	bool operator < (const Period& A) const {
		return pos < A.pos;
	}
} node[55][1005];
int main() {
//	freopen("input.txt", "r", stdin);
	int T; cin >> T;
	while(T--) {
		scanf("%d%d%I64d", &m, &n, &x);
		for(int i = 1; i <= m; i++)
			for(int j = 1; j <= n; j++) scanf("%I64d", &node[i][j].pos);
		for(int i = 1; i <= m; i++)
			for(int j = 1; j <= n; j++) scanf("%I64d", &node[i][j].e);
		for(int i = 1; i <= n; i++) node[1][i].dp = abs(node[1][i].pos-x)+node[1][i].e;
		sort(node[1]+1, node[1]+1+n);
		for(int i = 2; i <= m; i++) {
			sort(node[i]+1, node[i]+1+n);
			int cur = 1;
			LL t = INF;
			for(int j = 1; j <= n; j++) {
				while(cur <= n && node[i-1][cur].pos <= node[i][j].pos) {
					t = min(t, node[i-1][cur].dp-node[i-1][cur].pos);
					cur++;
				}
				node[i][j].dp = t+node[i][j].e+node[i][j].pos;
			}	
			cur = n;
			t = INF;
			for(int j = n; j >= 1; j--) {
				while(cur>=1 && node[i-1][cur].pos >= node[i][j].pos) {
					t = min(t, node[i-1][cur].dp+node[i-1][cur].pos);
					cur--;
				}
				node[i][j].dp = min(node[i][j].dp, t+node[i][j].e-node[i][j].pos);
			}		
		} 
		LL ans = INF;
		for(int i = 1; i <= n; i++) ans = min(ans, node[m][i].dp);
		cout << ans << endl;
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 4362 Dragon Ball(维护最小值DP优化)

标签:hdu

原文地址:http://blog.csdn.net/u014664226/article/details/47354015

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!