zoukankan      html  css  js  c++  java
  • Blocks && Fixing the Great wall

    读完大概都能发现是dp

    方法都很套路

    首先第一个题每次取的是一段区间,就能够想到区间dp

    按照区间dp的模板能够想到一种裸的方法:

    (dp[i][j]) 表示处理完 ([i...j]) 的最大分数

    然后你会发现这种方法连样例1都不能搞定

    因为 (dp[i][j]) 可能受到后面一些同色块的影响,导致直接处理不能获得最优值

    那怎么办?

    哪有问题就解决哪里

    添加一位 (k), 表示 区间右还有与块 (j) 颜色相同的 (k) 个块

    怎么转移?

    1. 直接把 ([j,j+k]) 这段区间领出来处理分数
    2. 找到 (j) 之前的一个与 (j) 颜色相同的块,然后把 ([p+1,j]) 剖出来,剩下 ([i,p,k+1]) 接着 (dp)

    实现可以采用线性或者记忆化

    int n, Case ;
    int col[N], hd[N], nxt[N] ;
    ll dp[N][N][N] ;
    
    ll dfs(int i, int j, int k) {
    	if (i > j) return 0 ;
    	if (dp[i][j][k] >= 0) return dp[i][j][k] ;
    	ll& ans = dp[i][j][k] ;
    	ans = dfs(i, j - 1, 0) + (k + 1) * (k + 1) ;
    	for (int p = nxt[j]; p >= i; p = nxt[p])
    	chmax(ans, dfs(i, p, k + 1) + dfs(p + 1, j - 1, 0)) ;
    	return ans ;
    }
    
    signed main() {
    	int T ; scanf("%d", &T) ;
    	while (T--) {
    		ass(dp, -1) ; clr(nxt) ; clr(hd) ;
    		scanf("%d", &n) ;
    		rep(i, 1, n) {
    			scanf("%d", &col[i]) ;
    			nxt[i] = hd[col[i]] ;
    			hd[col[i]] = i ;
    		}
    		printf("Case %d: %lld
    ", ++Case, dfs(1, n, 0)) ;
    	}
    	return 0 ;
    }
    

    第二个题就更套路了,我怎么记得我做过这个题

    好像是关路灯吧我也忘记了

    有一个结论是,把这些缺口排成一排,不可能先走过这个点不修走过去,然后又走回来修,这样肯定是不优的

    换句话说,就是修的段肯定是一个连续的区间

    配合数据范围提示能够想到区间 (dp)

    (dp[i][j][0/1]) 表示 当前处理了区间 ([i...j]),当前在 (i)(j) 的 方案数的最小代价

    (dp[l][r][0]=min(dp[l-1][r][0]+len(l-1,l)/v*cost, dp[l][r+1][1]+len(l,r+1)/v*cost))
    (dp[l][r][1]=min(dp[l-1][l][0]+len(l-1,r)/v*cost, dp[l][r+1][1]+len(r,r+1)/v*cost))

    (cost) 就是这一段走的代价,可以通过前缀和处理

    注意将开始节点也塞进去,(n+1) 个点进行 $dp $

    orz you

    
    struct node {
        double pos, c, del ;
        bool operator < (const node &a) const {
    		return pos < a.pos ;
    	}
    } a[N] ;
    
    int n, v, x ;
    double sum[N], dp[N][N][2] ;
    
    double dfs(int ll, int rr, int d) {
        if (ll == 1 && rr == n + 1) return 0 ;
        if (dp[ll][rr][d] != iinf) return dp[ll][rr][d] ;
        double resl = 0, resr = 0, w = sum[n + 1] - (sum[rr] - sum[ll - 1]) ;
        if (ll > 1) {
            if (d == 1) resl = (a[rr].pos - a[ll - 1].pos) / v * w ;
            else resl = (a[ll].pos - a[ll - 1].pos) / v * w ;
        }
        if (rr <= n) {
            if (d == 1) resr = (a[rr + 1].pos - a[rr].pos) / v * w ;
            else resr = (a[rr + 1].pos - a[ll].pos) / v * w ;
        }
        if (ll > 1) chmin(dp[ll][rr][d], dfs(ll - 1, rr, 0) + resl) ;
        if (rr <= n) chmin(dp[ll][rr][d], dfs(ll, rr + 1, 1) + resr) ;
        return dp[ll][rr][d] ;
    }
    
    int main() {
        while (scanf("%d%d%d", &n, &v, &x) != EOF && n && v && x) {
            double ssum = 0 ;
            rep(i, 1, n) scanf("%lf%lf%lf", &a[i].pos, &a[i].c, &a[i].del) ;
            a[n + 1] = (node) {x, 0, 0} ;
            sort(a + 1, a + n + 2) ;
            rep(i, 1, n + 1) ssum += a[i].c, sum[i] = sum[i - 1] + a[i].del ;
    		rep(i, 1, n + 1)
    		rep(j, 1, n + 1)
            dp[i][j][0] = dp[i][j][1] = iinf ;
            rep(i, 1, n + 1)
            if (a[i].pos == x) {
                printf("%.0lf
    ", floor(dfs(i, i, 0) + ssum)) ;
                break ;
            }
        }
        return 0 ;
    }
    
  • 相关阅读:
    iOS开发之ImageView复用实现图片无限轮播
    IOS 通过脚本自动打包工具 webfrogs/xcode_shell
    (iOS)判断GPS坐标是否在中国
    如何轻松实现iOS9多任务管理器效果(iCarousel高级教程)
    有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?
    PID控制算法的C语言实现四 增量型PID的C语言实现
    PID控制算法的C语言实现三 位置型PID的C语言实现
    PID控制算法的C语言实现二 PID算法的离散化
    PID控制算法的C语言实现一 PID算法原理
    人生是一个连续的过程,没什么东西能影响人的一生,怎么选择不是问题。问题是每天都要努力 (转)
  • 原文地址:https://www.cnblogs.com/harryhqg/p/Blocks-FixingtheGreatWall.html
Copyright © 2011-2022 走看看