hdu5550(计数DP+前缀和)

题意:每层楼有ai个人打羽毛球,有bi个人游泳,每层楼只能建造一个羽毛球场或者游泳馆,如果当前楼层没有羽毛求场,这ai个人就要到最近有羽毛球场的楼层打羽毛球,每个人产生的代价为楼层差,游泳的类似,求最小代价

这个貌似并没有用到什么很特殊的技巧可是就是莫名地难想。。不造为什么。。

首先由于楼层上下的情况都会对当前楼层产生影响,所以不能一层一层地往上考虑。。

那就只能一段一段考虑了。。对一段区间[l,r],假设他都用于建造羽毛球场,那么游泳的人由区间中点分开分别到l-1和r+1去游泳,所以当一段区间用于建造羽毛球或者游泳馆,我们是可以预处理的。。中点分开用前缀差分一下就可以了。。

预处理完用DP成段更新即可。。不过要注意第一段和最后一段的人只能往一个方向移动,所以应该单独出来讨论处理。。

 

 

 

#include<bits/stdc++.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge*j=h[x];j;j=j->next)
#define eps 1e-8
#define mid (x+y>>1)
#define lowbit(x) (x&(-x))
#define ll long long
#define sqr(x) ((x)*(x))
#define mem(a) memset(a,0,sizeof(a))
#define succ(x) (1<<(x))
#define NM 4005
using namespace std;
const ll inf=1e18;
const double pi=acos(-1);
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}











int n,ca;
ll a[NM],b[NM],_a[NM],_b[NM],f[NM],g[NM],ans;


ll c(int i,int j){
    int t=i+j>>1;
    return _a[t]-_a[i-1]-(i-1)*(a[t]-a[i-1])+(a[j]-a[t])*(j+1)-(_a[j]-_a[t]);
}
ll d(int i,int j){
    int t=i+j>>1;
    return _b[t]-_b[i-1]-(i-1)*(b[t]-b[i-1])+(b[j]-b[t])*(j+1)-(_b[j]-_b[t]);
}

int main(){
    //freopen("data.in","r",stdin);
    int _=read();while(_--){
	n=read();
	inc(i,1,n)a[i]=read(),b[i]=read();
	inc(i,1,n)_a[i]=a[i]*i,_b[i]=b[i]*i;
	inc(i,1,n)_a[i]+=_a[i-1],_b[i]+=_b[i-1],a[i]+=a[i-1],b[i]+=b[i-1];
	inc(i,1,n-1)g[i]=(i+1)*b[i]-_b[i],f[i]=(i+1)*a[i]-_a[i];
	g[n]=f[n]=inf;
	inc(i,2,n){
	    inc(j,1,i-1)f[i]=min(f[i],g[j]+c(j+1,i)),g[i]=min(g[i],f[j]+d(j+1,i));
	}
	ans=inf;
	//inc(i,1,n)inc(j,i,n)printf("%d %d:%lld %lld\n",i,j,c(i,j),d(i,j));
	inc(i,1,n-1){
	    ans=min(ans,g[i]+(_a[n]-_a[i])-i*(a[n]-a[i]));
	    ans=min(ans,f[i]+(_b[n]-_b[i])-i*(b[n]-b[i]));
	}
	printf("Case #%d: %lld\n",++ca,ans);
    }
    return 0;
}

 

 

 

 

 

Game Rooms

Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 989    Accepted Submission(s): 321


 

Problem Description

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.

 

 

Input

The first line of the input gives the number of test cases, T(1≤T≤100). T test cases follow. Each test case begins with one line with an integer N(2≤N≤4000), the number of floors in the building. N lines follow, each consists of 2 integers, Ti and Pi(1≤Ti,Pi≤109), the number of table tennis and pool players on the ith floor. The lines are given in increasing order of floor number, starting with floor 1 and going upward.

 

 

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimal sum of distances.

 

 

Sample Input

 

1 2 10 5 4 3

 

 

Sample Output

 

Case #1: 9

Hint

In the first case, you can build a table tennis game room on the first floor and a pool game room on the second floor. In this case, the 5 pool players on the first floor will need to go one floor up, and the 4 table tennis players on the second floor will need to go one floor down. So the total distance is 9.

 

 

Source

The 2015 China Collegiate Programming Contest

 

 

Recommend

wange2014   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

 

Statistic | Submit | Discuss | Note

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值