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



题意: 在连续的 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;
}

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

时间: 2024-08-25 13:25:13

HDU 4362 Dragon Ball(维护最小值DP优化)的相关文章

HDU 4362 Dragon Ball 贪心DP

Dragon Ball Problem Description Sean has got a Treasure map which shows when and where the dragon balls will appear. some dragon balls will appear in a line at the same time for each period.Since the time you got one of them,the other dragon ball wil

hdu 4362 Dragon Ball

Dragon Ball                                                           Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2204    Accepted Submission(s): 770 Problem Description Sean has got a Trea

HDU 4362 Dragon Ball 线段树

#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <stack> #include <vector> #include <iostream> #include <algorithm> using namespace st

hdu 4734 F(x)(数位dp+优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 题意:我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字. 题目给出a,b,求出0~b有多少个不大于f(a)的数 显然这题可以设这样的dp dp[len][count]表示前len位权值为count的有多少,然后显然的在len==0时return count>=f(a); 但是这样

HDU 3507 Print Article(斜率DP优化)

Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it to print articles. But it is too old to work for a long time and it will certainly wear and tear, so Zero use a cost to evaluate t

HDU4362Dragon Ball【dp优化】

[比赛提醒]BestCoder 你报名了吗?(点击报名) [科普]什么是BestCoder?如何参加? Dragon Ball Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2196    Accepted Submission(s): 767 Problem Description Sean has got a Treasure ma

hdu 2993 MAX Average Problem (斜率优化dp入门)

MAX Average Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5855    Accepted Submission(s): 1456 Problem Description Consider a simple sequence which only contains positive integers as

HDU 1024 Max Sum Plus Plus --- dp+滚动数组

HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值,其中第i个子序列包括a[j], 则max(dp[m][k]),m<=k<=n 即为所求的结果 <2>初始状态: dp[i][0] = 0, dp[0][j] = 0; <3>状态转移: 决策:a[j]自己成为一个子段,还是接在前面一个子段的后面 方程: a[j]直接接在前面

hdu 5623 KK&#39;s Number(dp)

问题描述 我们可爱的KK有一个有趣的数学游戏:这个游戏需要两个人,有N\left(1\leq N\leq 5*{10}^{4} \right)N(1≤N≤5∗10?4??)个数,每次KK都会先拿数.每次可以拿任意多个数,直到NN个数被拿完.每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大.在这样的情况下,最终KK的得分减去对手的得分会是多少? 输入描述 第一行一个数T\left( 1\leq T\leq 10\right)T(1≤T≤10),表示数据组