【HDU 5550 Game Rooms】题解

题目链接

题目

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 层有 \(T_i\) 个人打乒乓球,\(P_i\) 个人想游泳。
如果该层楼没有对应的功能室,对应的人只能去最近的楼层运动。
单个人爬一层楼的额外运动量是 1,问最合理的设计下,满足每个人的需求时,最少付出的额外运动量总和是多少。

\(N <= 4000,\ 0 <= T_i,P_i <= 10^{9}\)

思路

\(dp(i, k)\) 表示第 \(i\) 层修建设施 \(k\),且第 \(i+1\) 层修建另一种建筑物,前 \(i\) 层的最小代价。

然后我们枚举一个楼层 \(j\),使 \([j+1, i]\) 层都修建建筑 \(k\),然后我们再让 \([j+1, i]\) 不是 \(k\) 的人去 \(j\)\(i+1\) 层去。

\[\Large dp(i, k)=\min_{j=1}^{i-1}dp(j, k)+go(j+1, i, k') \]

初始化我们假设前 \(i\) 层都修建建筑 \(k\)

注意在转移过程中我们就要统计答案,我们可以假设 \([i+1, n]\) 都修建建筑 \(k'\)

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){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; 

int goup(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]); 
}

int godown(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); 
}

int go(int l, int r, int k)
{
	mid=(l+r)>>1; 
	return godown(l, mid, k)+goup(mid+1, r, k); 
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	T=read(); 
	while(T--)
	{
		n=read(); 
		for(i=0; i<n*2; ++i)
		{
			x=read(); 
			sum[i/2+1][i&1]=sum[i/2][i&1]+x; 
			dsm[i/2+1][i&1]=dsm[i/2][i&1]+x*(i/2+1); 
		}
		ans=0x3f3f3f3f3f3f3f3f; 
		for(i=1; i<n; ++i)
		{
			dp[i][0]=goup(1, i, 1); 
			dp[i][1]=goup(1, i, 0); 
			for(j=1; j<i; ++j)
			{
				dp[i][0]=min(dp[i][0], dp[j][1]+go(j+1, i, 1)); 
				dp[i][1]=min(dp[i][1], dp[j][0]+go(j+1, i, 0)); 
			}
			ans=min(ans, dp[i][0]+godown(i+1, n, 0)); 
			ans=min(ans, dp[i][1]+godown(i+1, n, 1)); 
		}
		printf("Case #%lld: %lld\n", ++t, ans); 
	}
	return 0; 
}
posted @ 2021-12-08 18:13  zhangtingxi  阅读(218)  评论(0编辑  收藏  举报