P1622 释放囚犯

Posted mzg1805

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1622 释放囚犯相关的知识,希望对你有一定的参考价值。

$\\colorCyan>>Question$

随着题量的上升,见的模型也越来越多

动态规划,明确的状态定义,明确的转移,明确的边界(有时边界比转移更重要)

比如此题,最开始我并没有看出是区间$dp$,但我突然想起紫书上一道题,"割木棍"

仔细想想,几乎与此题一样

最开始,我定义$f[i,j]$表示端点$i$到端点$j$的最小代价,枚举切割点$k$

$$f[i,j] = \\underseti<k<jmin\\left \\f[i,k]+f[k,j]  \\right \\+(a[j]-a[i]+1)-1$$

但这样定义,$f$转移时就发生了重合,如下图

技术图片

改变定义,令$f[i,j]$表示$i$到$j$(不包括端点$i$和$j$)的最小代价

$$f[i,j] = \\underseti<k<jmin\\left \\f[i,k]+f[k,j]  \\right \\+(a[j]-a[i]-1)-1$$

这样便是对的,如下图

技术图片

代码如下

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define ll long long
 6 //#include <stack>
 7 using namespace std;
 8 
 9 template <typename T> void in(T &x) 
10     x = 0; T f = 1; char ch = getchar();
11     while(!isdigit(ch)) if(ch == -) f = -1; ch = getchar();
12     while(isdigit(ch)) x = 10*x + ch - 0; ch = getchar();
13     x *= f;
14 
15 //------------------------------------------------------------
16 
17 const int N = 105;
18 
19 int m,n,a[N],f[N][N];
20 
21 int dp(int i,int j) 
22     int &_f = f[i][j];
23     if(_f) return _f;
24     //if(i == j) return 0;
25     if(i+1 == j) return 0;
26     int tmp = 0x3f3f3f3f;
27     for(int k = i+1;k <= j-1; ++k) tmp = min(tmp,dp(i,k)+dp(k,j));
28     return _f = tmp+a[j]-a[i]-2;//-2
29 
30 
31 int main() 
32     freopen("0.in","r",stdin);
33     in(m); in(n);
34     for(int i = 1;i <= n; ++i) in(a[i]);
35     sort(a+1,a+n+1); a[0] = 0; a[n+1] = m+1;//0,m+1
36     //memset(f,0x3f,sizeof(f));
37     cout << dp(0,n+1);
38     return 0;
39 

 

以上是关于P1622 释放囚犯的主要内容,如果未能解决你的问题,请参考以下文章

P1622 释放囚犯(区间dp)

P1622 释放囚犯(区间dp)

洛谷P1622 释放囚犯

P1622 释放囚犯

P1622释放囚犯

区间DP释放囚犯