码迷,mamicode.com
首页 > 其他好文 > 详细

UESTC 1225(dp……另附对拍器

时间:2015-10-30 20:41:58      阅读:515      评论:0      收藏:0      [点我收藏+]

标签:

题目:有一栋楼,每层楼上有t个人打网球,有p个人游泳,但是每层只能建一种健身设施。每个人的花费是他到最近的对应设施的楼层距离。问最小总花费。

思路:dp[i][j][k]表示做到第i层的时候选j,和j不同的设施最近在第k层的最小花费,那么如果该层选得和上面一样那么k不变,这个好转移。如果和上一层不一样,那么k层到当前层i的玩家会有一部分重新分布(他们的选择显然以中点为准),这个需要预处理一下(我写得很恶心。。。)。然后wa了整整一天,最后找了个代码对拍了一下才过(基本上完全是对的,,有个初始化没做。。。真是哔了狗。。)。这个对拍器真是好使啊。。。。

丑陋的代码。。

技术分享
/*
* @author:  Cwind
*/
#include <bits/stdc++.h>

using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-10)
#define IINF (1<<29)
#define LINF (1ll<<49)
#define INF (1000000300)
#define FINF (1e9)
#define clr(x) memset((x),0,sizeof (x))
#define cp(a,b) memcpy((a),(b),sizeof (b))
#define mset(x,v) memset((x),(v),sizeof (x))

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;

const int maxn=5000;
int T;
int n;
ll t[maxn],p[maxn];
ll ts[2][maxn],ps[2][maxn];
ll tmm[2][maxn],pm[2][maxn];
ll dp[2][2][maxn];
void cal(){
    for(int i=1;i<=n;i++){
        ts[0][i]=ts[0][i-1]+t[i];
        ps[0][i]=ps[0][i-1]+p[i];
        tmm[0][i]=tmm[0][i-1]+t[i]*i;
        pm[0][i]=pm[0][i-1]+p[i]*i;
    }
    ts[1][n+1]=ps[1][n+1]=0;
    tmm[1][n+1]=pm[1][n+1]=0;
    for(int i=n;i>=1;i--){
        ts[1][i]=ts[1][i+1]+t[i];
        ps[1][i]=ps[1][i+1]+p[i];
        tmm[1][i]=tmm[1][i+1]+t[i]*(n-i+1);
        pm[1][i]=pm[1][i+1]+p[i]*(n-i+1);
    }
}
ll get(bool o,int l,int r){
    int m=(r+l)/2;
    if(o){
        if(l==0) return tmm[1][1]-tmm[1][r+1]-(ts[1][1]-ts[1][r+1])*(n-r+1);
        ll oc=tmm[0][r]-tmm[0][l-1]-(ts[0][r]-ts[0][l-1])*l;
        ll nc=tmm[0][m]-tmm[0][l-1]-(ts[0][m]-ts[0][l-1])*l+tmm[1][m+1]-tmm[1][r+1]
                -(ts[1][m+1]-ts[1][r+1])*(n-r+1)+t[r]*(r-l);
        return nc-oc;
    }else{
        if(l==0) return pm[1][1]-pm[1][r+1]-(ps[1][1]-ps[1][r+1])*(n-r+1);
        ll oc=pm[0][r]-pm[0][l-1]-(ps[0][r]-ps[0][l-1])*l;
        ll nc=pm[0][m]-pm[0][l-1]-(ps[0][m]-ps[0][l-1])*l+pm[1][m+1]-pm[1][r+1]
                -(ps[1][m+1]-ps[1][r+1])*(n-r+1)+p[r]*(r-l);
        return nc-oc;
    }
}
int cas;
int main(){
    //freopen("/home/slyfc/CppFiles/in","r",stdin);
    //freopen("/home/slyfc/CppFiles/out","w",stdout);
    cin>>T;
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)      
            scanf("%lld%lld",&t[i],&p[i]);
        cal();
        for(int i=0;i<2;i++)
            for(int k=0;k<2;k++)
                for(int j=0;j<maxn;j++)
                    dp[i][k][j]=LINF;
        dp[0][0][0]=dp[0][1][0]=0;
        dp[1][0][0]=dp[1][1][0]=0;
        bool f=0;
        for(int i=2;i<=n;i++){
            f^=1;
            for(int j=1;j<i-1;j++){
                dp[f][0][j]=dp[f^1][0][j]+p[i]*(i-j);
                dp[f][1][j]=dp[f^1][1][j]+t[i]*(i-j);
            }
            for(int j=0;j<i-1;j++){
                dp[f][0][i-1]=min(dp[f][0][i-1],dp[f^1][1][j]+p[i]+get(1,j,i));
                dp[f][1][i-1]=min(dp[f][1][i-1],dp[f^1][0][j]+t[i]+get(0,j,i));
            }
        }
        ll ans=LINF;
        for(int i=1;i<n;i++){
            ans=min(ans,dp[f][1][i]);
            ans=min(ans,dp[f][0][i]);
        }
        printf("Case #%d: %lld\n",++cas,ans);
    }
    return 0;    
}
View Code

对拍器

while true; do
./make>inData #出数据
./myCpp<inData>myOut #被测程序
./stdCpp<inData>stdOut #正确(暴力)程序
if diff myOut stdOut; then #比较两个输出文件
printf AC #结果相同显示AC
else
echo WA #结果不同显示WA,并退出
#cat tmp.out tmp2.out
exit 0
fi #if的结束标志,与C语言相反,0为真
done # while的结束标志

#BY NICK WONG 2014-08-29
#在终端下,进入当前目录,输入"sh ./nick.sh",(其中nick.sh为当前shell脚本名) #表示单行注释
#diff在两文件相同时返回空串

对拍器转自:http://blog.csdn.net/nickwong_/article/details/38931579

UESTC 1225(dp……另附对拍器

标签:

原文地址:http://www.cnblogs.com/Cw-trip/p/4924271.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!