洛谷 P1622 释放囚犯(区间dp)

传送门


解题思路

感觉还是蛮有难度的。

设dp[i][j]表示释放编号在区间i..j的犯人所需要的肉的数量。

一开始枚举最后一个释放的人k进行转移,结果发现wa了,为什么?

深入分析一下,发现不满足无后效性,即未来的决策会影响现在的答案。
因为k左右两边的转移是相互影响的。

而当我们枚举的k的意义变成第一个释放的人,就会正确。

因为k使得左右区间间隔开,不会互相影响到。

剩下的就是普通的区间dp了。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=105;
int n,m,a[maxn],dp[maxn][maxn];
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=m;i++) cin>>a[i];
	sort(a+1,a+m+1);
	a[m+1]=n+1;
	for(int i=1;i<=m;i++) dp[i][i]=a[i+1]-a[i-1]-2;
	for(int len=2;len<=m;len++){
		for(int i=1;i<=m;i++){
			int j=i+len-1;
			if(j>m) break;
			dp[i][j]=min(dp[i+1][j],dp[i][j-1])+a[j+1]-a[i-1]-2;
			for(int k=i;k<=j;k++){
				dp[i][j]=min(dp[i][j],dp[i][k-1]+dp[k+1][j]+a[j+1]-a[i-1]-2);
			}
		}
	}
	cout<<dp[1][m];
	return 0;
}
posted @ 2021-09-27 16:40  尹昱钦  阅读(65)  评论(0编辑  收藏  举报