hdu4326 Dragon Ball 单调队列优化Dp
来源:互联网 发布:涟源行知中学校花图片 编辑:程序博客网 时间:2024/05/16 10:30
/* 题目描述:一个有m个回合,每回合会出现n个龙珠,每个龙珠的位置是ball[i][j].p,得到龙珠的消耗是ball[i][j].c,每回合出现 的龙珠只能选择其中的一个,每回合消耗的体力为获得上一个龙珠到这一个龙珠的距离加上获取这一个龙珠的消耗,问 m回合过后,消耗的体力最小是多少。 方法:dp[i][j]的含义是在第i回合取第i个龙珠,在这种决策下的总的最小消耗的体力,于是有 dp[i][j] = min(dp[i - 1][k] + abs(ball[i][j].p - ball[i - 1][k].p) + ball[i][j].c) 这样如果不经优化转移的复杂度为O(n^2 * m),显然不满足要求,如果使用单调队列进行优化,时间复杂度可以降为O(n * m) 因为单调队列优化dp的形式往往是dp[i] = min/max(dp[k]) + f[i] ,其中i与k无关,但abs(ball[i][j].p - ball[i - 1][k].p)+ ball[i][j].c 部分依然含k,故首先要去掉绝对值,方程变为 dp[i][j] = min(dp[i - 1][k] - ball[i - 1][k].p) + ball[i][j].p + ball[i][j].c ; (满足ball[i][j].p >= ball[i - 1][k].p) dp[i][j] = min(dp[i - 1][k] + ball[i - 1][k].p) - ball[i][j].p + ball[i][j].c ; (满足ball[i][j].p < ball[i - 1][k].p) 可以使用单调队列两次进行优化*/#pragma warning(disable:4786)#pragma comment(linker, "/STACK:102400000,102400000")#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>#include<queue>#include<map>#include<set>#include<vector>#include<cmath>#include<string>#include<sstream>#include<bitset>#define LL long long#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)#define mem(a,x) memset(a,x,sizeof(a))#define lson l,m,x<<1#define rson m+1,r,x<<1|1using namespace std;const int INF = 0x3f3f3f3f;const int mod = 1e9 + 7;const double PI = acos(-1.0);const double eps=1e-6;const int maxn = 1e3 + 5;LL dp[55][maxn];struct node{ int p , c; bool operator < (const node & rhs)const{ return p < rhs.p; }}ball[55][maxn];LL q[maxn];int main(){ int T , n , m , x; scanf("%d",&T); while(T--){ scanf("%d%d%d", &m , &n , &x); for(int i = 1 ; i<= m ; i++){ for(int j = 1 ; j<= n ; j++){ scanf("%d", &ball[i][j].p); dp[i][j] = INF; } } for(int i = 1 ;i<= m ;i++){ for(int j = 1 ;j<=n ;j++ ){ scanf("%d", &ball[i][j].c); } sort(ball[i] + 1 , ball[i] + n + 1); } for(int i = 1 ; i <= n ; i++ ){ dp[1][i] = abs(ball[1][i].p - x) + ball[1][i].c; } for(int i = 2 ; i<= m ; i++){ int head , tail , cur, nowf; head = tail = 0; cur = 1; q[head] = INF; //一开始在将q[head]置为INF,目的是当队列里无元素时转移的结果没有意义 for(int j = 1 ; j<= n ; j++){ while(cur <= n && ball[i][j].p >= ball[i - 1][cur].p){ //这样两层循环推进复杂度是O(2n),显示出排序的意义 nowf = dp[i - 1][cur] - ball[i - 1][cur].p; while(head < tail && q[tail - 1] >= nowf){ //head == tail时队列为空,q[tail - 1]为队列中最后一个元素 --tail; } q[tail++] = nowf; ++cur; } //在第i个回合,处理的是i-1回合中的dp[i - 1][cur] - ball[i - 1][cur].p,然后根据处理结果更新dp[i][j] dp[i][j] = min(dp[i][j] , q[head] + ball[i][j].p + ball[i][j].c); } head = tail = 0 ; cur = n; q[head] = INF; for(int j = n ; j>= 1 ; j--){ while(cur >= 1 && ball[i][j].p < ball[i - 1][cur].p){ nowf = dp[i - 1][cur] + ball[i - 1][cur].p; while(head < tail && q[tail - 1] >= nowf){ --tail; } q[tail++] = nowf; --cur; } dp[i][j] = min(dp[i][j] , q[head] - ball[i][j].p + ball[i][j].c); } } LL ans = INF; for(int i = 1 ; i <= n ;i++){ ans = min(ans , dp[m][i]); } printf("%lld\n",ans); } return 0;}
0 0
- hdu4326 Dragon Ball 单调队列优化Dp
- hdu4362 Dragon Ball(dp+单调队列优化)
- hdu 4362 Dragon Ball 单调队列优化 dp
- MUTC7 C - Dragon Ball 单调队列dp
- hdu_4362 Dragon Ball (DP+单调栈)
- hdu 4362 Dragon Ball(优先队列+dp)
- HDU 3872 Dragon Ball(DP+线段树+单调栈)
- 单调队列优化DP
- 单调队列优化DP
- dp单调队列优化
- 单调队列--优化dp
- 单调队列优化dp
- 单调队列优化DP
- 单调队列优化DP
- 单调队列优化dp
- HDU_3872 Dragon Ball dp
- 【DP】 hdu4362 Dragon Ball
- HDU 4362 Dragon Ball(维护最小值DP优化)
- 如何用rvest包爬取豆瓣图书250的数据
- paxos算法概念入门
- 微信开发(一)内网映射之natapp的使用
- java Thread中,run方法和start方法的区别
- Servlet-重定向与转发
- hdu4326 Dragon Ball 单调队列优化Dp
- Servlet-Cookie 与 Session
- Maven学习总结(32)——Maven项目部署到Tomcat8中
- Eclipse如何快速修改工程名及包名
- 【例题】【主席树】
- java递归无级树输出json格式
- Oracle sql语句执行顺序
- Visual Studio 2013 Tools for Unity(简VSTU)
- iOS邮箱、手机号等常用验证功能