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 ;
}
原文地址:https://www.cnblogs.com/harryhqg/p/Blocks-FixingtheGreatWall.html