hdu5550Game Rooms

来源:互联网 发布:淘宝店铺添加手机桌面 编辑:程序博客网 时间:2024/06/05 08:05

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5550

题意:有n层楼,每层有p[i]个人喜欢网球t[i]个人喜欢游泳,每层楼只能建一个娱乐场所,没有场所的人要去其他楼,求建好娱乐场所后所有人到离他最近的喜欢的娱乐场所的总和最小。

分析:设dp[i][j][0/1]表示第i层建0/1,j<i并且第j层是第一个与第i层不同娱乐场所的层,注意下第i层是第一次建当前种娱乐场所这个边界。

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<bitset>#include<math.h>#include<vector>#include<string>#include<stdio.h>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=4010;const int mod=100000000;const int MOD1=1000000007;const int MOD2=1000000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const int MAX=1000000010;const ll INF=1ll<<55;const double pi=acos(-1.0);typedef double db;typedef unsigned long long ull;ll x[N],y[N],dp[2][N][2];ll sumx[N],sumy[N],ssumx[N],ssumy[N];void init(int n) {    sumx[0]=sumy[0]=0;    ssumx[0]=ssumy[0]=0;    for (int i=1;i<=n;i++) {        scanf("%lld%lld", &x[i], &y[i]);        sumx[i]=sumx[i-1]+x[i];sumy[i]=sumy[i-1]+y[i];    }    for (int i=1;i<=n;i++) {        ssumx[i]=ssumx[i-1]+sumx[i];        ssumy[i]=ssumy[i-1]+sumy[i];    }}ll cala(int rev,int l,int r) {    ll ret;    int mid=(l+r)>>1;    if (rev) {        ret=2*(ssumy[r]-ssumy[mid]-(ll)(r-mid)*sumy[mid])-(ll)(r-l+2)*(sumy[r]-sumy[mid]);    } else {        ret=2*(ssumx[r]-ssumx[mid]-(ll)(r-mid)*sumx[mid])-(ll)(r-l+2)*(sumx[r]-sumx[mid]);    }    return ret;}ll solve(int n) {    int i,j,k,now,pre;    ll ret=INF;now=pre=1;    dp[now][0][0]=dp[now][0][1]=INF;    for (i=2;i<=n;i++) {        pre=now;now^=1;        for (j=0;j<i;j++) dp[now][j][0]=dp[now][j][1]=INF;        dp[now][i-1][0]=y[i]+ssumx[i-1];        dp[now][i-1][1]=x[i]+ssumy[i-1];        for (j=1;j<i-1;j++) {            dp[now][j][0]=min(dp[now][j][0],dp[pre][j][0]+(ll)(i-j)*y[i]);            dp[now][j][1]=min(dp[now][j][1],dp[pre][j][1]+(ll)(i-j)*x[i]);        }        for (j=1;j<i-1;j++) {            dp[now][i-1][0]=min(dp[now][i-1][0],dp[pre][j][1]+y[i]+cala(0,j+1,i-1));            dp[now][i-1][1]=min(dp[now][i-1][1],dp[pre][j][0]+x[i]+cala(1,j+1,i-1));        }    }    for (i=1;i<n;i++) {        ret=min(ret,dp[now][i][0]);ret=min(ret,dp[now][i][1]);    }    return ret;}int main(){    int i,n,t,ca;    scanf("%d", &t);    for (ca=1;ca<=t;ca++) {        scanf("%d", &n);        init(n);        printf("Case #%d: %lld\n", ca, solve(n));    }    return 0;}


0 0