题意:每层楼有ai个人打羽毛球,有bi个人游泳,每层楼只能建造一个羽毛球场或者游泳馆,如果当前楼层没有羽毛求场,这ai个人就要到最近有羽毛球场的楼层打羽毛球,每个人产生的代价为楼层差,游泳的类似,求最小代价
这个貌似并没有用到什么很特殊的技巧可是就是莫名地难想。。不造为什么。。
首先由于楼层上下的情况都会对当前楼层产生影响,所以不能一层一层地往上考虑。。
那就只能一段一段考虑了。。对一段区间[l,r],假设他都用于建造羽毛球场,那么游泳的人由区间中点分开分别到l-1和r+1去游泳,所以当一段区间用于建造羽毛球或者游泳馆,我们是可以预处理的。。中点分开用前缀差分一下就可以了。。
预处理完用DP成段更新即可。。不过要注意第一段和最后一段的人只能往一个方向移动,所以应该单独出来讨论处理。。
#include
#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;
}
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