Your company has just constructed a new skyscraper, but you just noticed a terrible problem: there is only space to put one game room on each floor! The game rooms have not been furnished yet, so you can still decide which ones should be for table tennis and which ones should be for pool. There must be at least one game room of each type in the building.
Luckily, you know who will work where in this building (everyone has picked out offices). You know that there will be Ti table tennis players and Pi pool players on each floor. Our goal is to minimize the sum of distances for each employee to their nearest game room. The distance is the difference in floor numbers: 0 if an employee is on the same floor as a game room of their desired type, 1 if the nearest game room of the desired type is exactly one floor above or below the employee, and so on.
计划建设 N 层高的运动楼,每层楼要么建游泳池,要么建乒乓球室,只能二选一。
已知第 i 层有 Ti 个人打乒乓球,Pi 个人想游泳。
如果该层楼没有对应的功能室,对应的人只能去最近的楼层运动。
单个人爬一层楼的额外运动量是 1,问最合理的设计下,满足每个人的需求时,最少付出的额外运动量总和是多少。
N<=4000,0<=Ti,Pi<=109
思路
设 dp(i,k) 表示第 i 层修建设施 k,且第 i+1 层修建另一种建筑物,前 i 层的最小代价。
#include<bits/stdc++.h> usingnamespace std; #define int long long inlineintread(){int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+ (x<<3)+(ch^48);ch=getchar();}return x*f;} //#define M //#define mo #define N 4010 int n, m, i, j, k; int sum[N][2], dsm[N][2], dp[N][2]; int l, r, mid, x, ans, t, T;
intgoup(int l, int r, int k)// [l, r]-> r+1 { return (sum[r][k]-sum[l-1][k])*(r+1)-(dsm[r][k]-dsm[l-1][k]); }
intgodown(int l, int r, int k)// [l, r]->l-1 { return (dsm[r][k]-dsm[l-1][k])-(sum[r][k]-sum[l-1][k])*(l-1); }
intgo(int l, int r, int k) { mid=(l+r)>>1; returngodown(l, mid, k)+goup(mid+1, r, k); }