zoukankan      html  css  js  c++  java
  • P1622 释放囚犯

    ${color{Cyan}{>>Question}}$

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

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

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

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

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

    $$f[i,j] = underset{i<k<j}{min}left {f[i,k]+f[k,j]  ight }+(a[j]-a[i]+1)-1$$

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

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

    $$f[i,j] = underset{i<k<j}{min}left {f[i,k]+f[k,j]  ight }+(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 }
  • 相关阅读:
    C语言I博客作业10
    C语言I博客作业09
    C语言I博客作业08
    背景图
    C语言II作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言I博客作业12
  • 原文地址:https://www.cnblogs.com/mzg1805/p/11440325.html
Copyright © 2011-2022 走看看