zoukankan      html  css  js  c++  java
  • hdu5550 Game Rooms dp

    hdu5550 Game Rooms  dp

    调了一下午的bug终于过了。。。思路是没错的,但是由于用了刷表法思考,所以只考虑刷表之后的状态,没有注意刷表前的最初状态,于是调了一下午的bug终于找出来了。。。

    dp[i][j][k] 表示 前i个,最后一个k的位置为j ( k取0,1,j<i ) 的总花费。

    转移有两个,即第i+1个位置为0或者1:

    dp[i+1][j][k]=min(dp[i+1][j][k] , dp[i][j][k]+a[i+1][k]*(i+1-j)) 

    dp[i+1][i][!k]=min(dp[i+1][i][!k],  dp[i][j][k]+L(j+1,m,j,k)+L(m+1,i,i+1,k)-L(j+1,i,j,k)+a[i+1][!k])  (m为j和i+1的中点)

    这里有一点需要特别注意的是:

    由于过程中不存在全0或者全1的情况(0000或1111),所以000001不可能由00000推出来,这里需要预处理出所有的00001和111110,也就是将dp[i][i-1][k]的初值设为000001或1111110的值。

    另外还有一点,计算L(l,r,x,k)可以维护一个sum(i*a[i])和sum(a[i])来实现o(1)的计算。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=4010;
    const int INF=1<<29;
    
    int n;
    ll a[maxn][2],s[maxn][2],fs[maxn][2];
    ll si[maxn][2],fsi[maxn][2];
    ll dp[2][maxn][2];
    
    ll Pre(int l,int r,int x,int k)
    {
        if(l>r) return 0;
        return (si[r][k]-si[l-1][k])-(s[r][k]-s[l-1][k])*x;
    }
    
    ll Suf(int l,int r,int x,int k)
    {
        if(l>r) return 0;
        return (fsi[l][k]-fsi[r+1][k])-(fs[l][k]-fs[r+1][k])*(n-x+1);
    }
    
    ll L(int l,int r,int x,int k)
    {
        if(l>r) return 0;
        if(x<=l) return Pre(l,r,x,k);
        if(x>=r) return Suf(l,r,x,k);
        return Suf(l,x-1,x,k)+Pre(x+1,r,x,k);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
        int T;cin>>T;int casen=1;
        while(T--){
            scanf("%d",&n);
            REP(i,1,n) scanf("%I64d%I64d",&a[i][0],&a[i][1]);
            //out();
            s[0][0]=s[0][1]=0;
            si[0][0]=si[0][1]=0;
            REP(i,1,n){
                s[i][0]=s[i-1][0]+a[i][0];
                s[i][1]=s[i-1][1]+a[i][1];
                si[i][0]=si[i-1][0]+a[i][0]*i;
                si[i][1]=si[i-1][1]+a[i][1]*i;
            }
            fs[n+1][0]=fs[n+1][1]=0;
            fsi[n+1][0]=fsi[n+1][1]=0;
            for(int i=n;i>=1;i--){
                fs[i][0]=fs[i+1][0]+a[i][0];
                fs[i][1]=fs[i+1][1]+a[i][1];
                fsi[i][0]=fsi[i+1][0]+a[i][0]*(n-i+1);
                fsi[i][1]=fsi[i+1][1]+a[i][1]*(n-i+1);
            }
            MS0(dp);
            ll MAX=1LL<<60;
            memset(dp,0x3f3f3f,sizeof(dp));
            ll ans=MAX;
            dp[2%2][1][0]=a[1][1]+a[2][0];
            dp[2%2][1][1]=a[1][0]+a[2][1];
            REP(i,2,n-1){
                REP(j,1,i){
                    REP(k,0,1){
                        dp[(i+1)%2][j][k]=L(1,j,j+1,!k)+L(j+1,i+1,j,k);
                    }
                }
                REP(j,1,i-1){
                    REP(k,0,1){
                        dp[(i+1)%2][j][k]=min(dp[(i+1)%2][j][k],dp[i%2][j][k]+a[i+1][k]*(i+1-j));
                        int m=(j+i+1)>>1;
                        dp[(i+1)%2][i][!k]=min(dp[(i+1)%2][i][!k],dp[i%2][j][k]+L(j+1,m,j,k)+L(m+1,i,i+1,k)-L(j+1,i,j,k)+a[i+1][!k]);
                    }
                }
            }
            REP(i,1,n-1){
                //printf("dp[%d][%d][0]=%I64d dp[%d][%d][1]=%I64d
    ",n,i,dp[n%2][i][0],n,i,dp[n%2][i][1]);
                ans=min(ans,dp[n%2][i][0]);
                ans=min(ans,dp[n%2][i][1]);
            }
            printf("Case #%d: %I64d
    ",casen++,ans);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    蓝桥杯_买不到的数目
    蓝桥杯_错误票据
    蓝桥杯_数组操作
    剑指OFFER_把二叉树打印成多行
    C语言学习笔记_结构体的内存对齐
    剑指OFFER_二叉搜索树的第k个节点
    局域网ftp工具,带你去探索局域网ftp工具
    这就是Java代码生成器的制作流程(转载)
    ftp工具 绿色,一款非常棒的绿色 ftp工具
    HDFS+ClickHouse+Spark:从0到1实现一款轻量级大数据分析系统(转载)
  • 原文地址:https://www.cnblogs.com/--560/p/5070223.html
Copyright © 2011-2022 走看看