HDU 5550 Game Rooms (dp)
来源:互联网 发布:阿里云cdn怎么收费 编辑:程序博客网 时间:2024/06/05 08:10
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5550
题目:一共n层楼,每层楼都要建一个娱乐室,共有两种(球馆、游泳馆)可以选择,且n层楼中至少有1个球馆和游泳馆。现每层楼有Ti个球类爱好者,Pi个游泳爱好者,他们都要去各自的娱乐室娱乐,求一个建造方案,使得他们走的总路程的最小。(假设A在3楼,要去游泳。若游泳馆在3楼,则A走的路程为0;若游泳馆在2楼或4楼,则路程为1,;若在1楼或5楼,则路程为2.以此类推)。
思路:令dp(i, j)表示已经安排了前i层的人的最小花费,j为0或1,表示娱乐室的类别。我们让某一段连续楼层(从k开始)一直到i全为娱乐室j。易知,第k-1层和第i+1层均为j^1。
那么dp(i, j) = min{ dp(k, j^1) + dist(k+1, i) }, 其中dist(k+1, i)表示安排第k+1层到第i层人的最小花费,因为k+1到i层的娱乐室都一样,所以可以在常数时间内算出。总复杂度为O(n²)。
dist(k+1, j)的算法如下
#include<cstdio>#include<cstring>#include<vector>#include<iostream>#include<set>#include<algorithm>using namespace std;typedef long long ll;const int maxn = 4000 + 5;const ll INF = 1e15 + 10;int T[maxn], P[maxn], n;ll sumT[maxn], sumP[maxn], calT[maxn], calP[maxn];ll dp[maxn][2];ll toLeft(int L, int R, ll *sum, ll *cal) { return (cal[R] - cal[L-1]) - (L-1) * (sum[R] - sum[L-1]);}ll toRight(int L, int R, ll *sum, ll *cal) { return (R+1)*(sum[R]-sum[L-1]) - (cal[R] - cal[L-1]);}ll dist(int L, int R, int p) { // p为0代表L——R区间中全是球馆,p为1代表L——R区间中全是游泳馆 if(L == 1 && R == n) return INF; //n层楼全是一种是不合法的 else if(L == 1) { //只能去右边(即楼上) if(p == 1) return toRight(L, R, sumT, calT); return toRight(L, R, sumP, calP); } else if(R == n) { //只能去左边(即楼下) if(p == 1) return toLeft(L, R, sumT, calT); return toLeft(L, R, sumP, calP); } else { //去楼上楼下皆可,因此区间左半部分去楼下,右半部分去楼上 int x = (L + R) >> 1; if(p == 1) return toLeft(L, x, sumT, calT) + toRight(x+1, R, sumT, calT); return toLeft(L, x, sumP, calP) + toRight(x+1, R, sumP, calP); } }int main() { int test, kase = 0; scanf("%d", &test); while(test--) { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &T[i], &P[i]); sumT[i] = sumT[i-1] + T[i]; sumP[i] = sumP[i-1] + P[i]; calT[i] = calT[i-1] + (ll)i*T[i]; calP[i] = calP[i-1] + (ll)i*P[i]; } dp[0][0] = dp[0][1] = 0; for(int i = 1; i <= n; i++) for(int j = 0; j <= 1; j++) { dp[i][j] = INF; for(int k = 0; k < i; k++) dp[i][j] = min(dp[i][j], dp[k][j^1] + dist(k+1, i, j)); } printf("Case #%d: %lld\n", ++kase, min(dp[n][0], dp[n][1])); } return 0;}
0 0
- HDU 5550 Game Rooms(DP)
- HDU 5550 Game Rooms (dp)
- HDU 5550 Game Rooms(dp)
- hdu 5550 Game Rooms
- HDU 5550 Game Rooms (dp+前缀和预处理)
- UESTC 1225 Game Rooms
- hdu5550 Game Rooms
- hdu 3625 Examining the Rooms //组合数学DP
- Hdu 4701 Game -- DP
- [HDU 4701 Game] DP
- hdu 5218 Game (dp)
- dp- hdu 5218Game
- hdu5550 Game Rooms (动态规划)
- HDU Examining the Rooms
- hdu Examining the Rooms
- hdu - 4326 - Game - 概率dp
- hdu 1505 dp City Game
- 【树形DP】 HDU 4616 Game
- 解密ThreadLocal
- 带你飞过PMP—备考上篇•乖乖看书就对了-GZ1610吴慧敏
- Android中为什么主线程不会因为Looper.loop()里的死循环卡死?
- android6.0系统Healthd深入分析
- 关于EOF的几个问题
- HDU 5550 Game Rooms (dp)
- HTML+CSS学习路线
- centos7 安装 mariadb(mysq的一种) 的正确命令
- 【Java之IO】2.缓冲区
- Android之Intent
- JavaScript的运行机制Event Loop(事件循环)
- SON:如果你愿意一层一层剥开我的心,你会发现...这里水很深——深入理解JSON
- mysql备份、恢复数据库的方法
- Help Hanzo LightOJ