以前做过的几道常用DP 问题集合(以备以后记忆)

本文整理了几个经典的动态规划问题,包括石子并归问题、滑雪问题以及最长公共子序列问题。通过分析题意、输入输出格式和解题思路,帮助读者理解和掌握动态规划的应用。
摘要由CSDN通过智能技术生成

动态规划(石子并归问题)

题意:

有 n 个石子,把n 堆石子合并成一个,合并时候只能是相邻的两个石子,合并时能获得积分为合并两队石子的数目之和,问如何合并能或得最多或者最小的积分:

例如:4 个石子

输入:4 4 5 9 (为每一堆的石子个数,如果想让1 2 堆合并则得到积分 8)

输出 43 54

解题思路:

令f[i:j] 表示把第i 堆到 到第 j 堆合并得到的积分这有

f[i:j]={ f[i:k]+f[k+1][j]} (其中 k>=i k<j)

令max[i:j] 为表示把第i 堆到 到第 j 堆合并得到的积分最大值(或者最小值)有:

max[i:j]=max{ f[i:j]+max[i:k]+max[k+1:j];

其实这这类型的题目和矩阵相乘、能量项链的题目都是类似的

#include<iostream>
#define  Max 100
using namespace std;
int a[Max];
int p[Max][Max];//记录f[i:j]
int max[Max][Max];//
int s[Max][Max];// 记录为
void sovle_max(int n){//
 memset(p,0,sizeof(p));
 memset(max,0,sizeof(max));
 for(int i=1;i<=n;i++){
  p[i][i]=a[i];
 }
 for( int r=2;r<=n;r++){
  for(int i=1;i<=n-r+1;i++){
   int j=i+r-1;
   int temp=0;
   for(int k=i;k<j;k++){
    if(p[i][k]+p[k+1][j]+max[i][k]+max[k+1][j]>temp){
     temp=p[i][k]+p[k+1][j]+max[i][k]+max[k+1][j];
     p[i][j]=p[i][k]+p[k+1][j];
     s[i][j]=k;
    }
   }
   //p[i][j]=temp;
   max[i][j]=temp;
  }
 }
}
void sovle_min(int n){//
 memset(p,0,sizeof(p));
 memset(max,0,sizeof(max));
 for(int i=1;i<=n;i++){
  p[i][i]=a[i];
 }
 for( int r=2;r<=n;r++){
  for(int i=1;i<=n-r+1;i++){
   int j=i+r-1;
   int temp=(1<<30);
   for(int k=i;k<j;k++){
    if(p[i][k]+p[k+1][j]+max[i][k]+max[k+1][j]<temp){
     temp=p[i][k]+p[k+1][j]+max[i][k]+max[k+1][j];
     p[i][j]=p[i][k]+p[k+1][j];
     s[i][j]=k;
    }
   }
   //p[i][j]=temp;
   max[i][j]=temp;
  }
 }
}
void print(int n){
 for(int i=1;i<=n;i++){
  for(int j=1;j<=n;j++){
   cout<<max[i][j]<<" ";
  }
  cout<<endl;
 }
}
int main(void){
 int n;
 cin>>n;
 for(int i=1;i<=n;i++){
  cin>>a[i];
 }
 sovle_max(n);
 print(n);
 sovle_min(n);
 print(n);
}


 

 描述 Description   

   两个球队的支持者要一起坐车去看球,他们已经排成了一列。我们要让他们分乘若干辆巴士,同一辆巴士上的人必须在队伍中是连续的。为了在车上不起冲突,希望两队的支持者人数尽量相等,差至多是D。有一个例外,就是一辆车上的人全部都是一个球队的支持者。问要将这N个人全部送至球场,至少要几辆巴士。 

输入格式 Input Format  

   第一行是整数ND1<=N<=25001<=D<=N

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值