IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 一本通 动态规划专栏 -> 正文阅读

[数据结构与算法]一本通 动态规划专栏

数塔问题

【问题描述】

观察下面的数塔。写一个程序查找从最高点到底部任意位置结束的路径,使路径经过数字的和最大。
每一步可以从当前点走到左下角的点,也可以到达右下角的点。

image.png

【输入形式】

【输出形式】

【样例输入】

5
13
11 8
12 7 26
6 14 15 8
12 7 13 24 11
【样例输出】

max=86

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

ll n,dp[2005][2005];
ll a[2005][2005],maxn;

int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n ;
    for(int i = 1 ; i <= n ; i++ )
     for(int j = 1 ; j <= i ; j++ )
      cin >> a[i][j];
    memset(dp,-inf,sizeof dp);
    dp[1][1] = a[1][1];
    
    for(int i = 2 ; i <= n ; i ++ )
     for(int j = 1 ; j <= i ; j ++ )
      dp[i][j] = max(dp[i - 1][j] + a[i][j] , dp[i - 1][j - 1] + a[i][j]);
      
   maxn = dp[n][1];
   for(int i = 1 ; i <= n ; i++ ) maxn = max(maxn,dp[n][i]);
   cout<<"max="<<maxn;
	return 0;
}

最长不下降序列

【问题描述】

设有由n(1<=n<=200)个不相同的整数组成的数列,记为:b(1)、b(2)、……、b(n)且b(i)<>b(j)(i<>j),若存在i1<i2<i3< <="" p="" …="" 且有b(i1)<= ie="">
例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。例中13,16,18,19,21,22,63就是一个长度为7的不下降序列,同时也有7 ,9,16,18,19,21,22,63组成的长度为8的不下降序列。

【输入形式】

第一行为n,第二行为用空格隔开的n个整数。

【输出形式】

第一行为输出最大个数max(形式见样例);

第二行为max个整数形成的不下降序列,答案可能不唯一,输出一种就可以了,本题进行特殊评测。

【样例输入】

14

13 7 9 16 38 24 37 18 44 19 21 22 63 15

【样例输出】

max=8

7 9 16 18 19 21 22 63

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n , t,x , a[MAX] ,pre[MAX],bk,b[MAX],dp[MAX],ans;

int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1 ; i <= n ; i ++ ) cin >> a[i] ,dp[i] = 1;
    ans = 1;
    
    for(int i = 1 ; i <= n ; i ++ ){
    	 for(int j = 1 ; j < i ; j++)
    	  if(a[i] >= a[j]){
    	  	  dp[i] = max(dp[i] , dp[i] = dp[j] + 1);
    	  	   pre[i] = j;
    	  
		  }
		  if(dp[i] > ans){
		  	 ans = dp[i];
		  	 bk = i;
		  }
	}
	cout<<"max="<<ans<<"\n";
	while(bk){
	   	b[++t] = a[bk];
	   	bk=pre[bk];
	}
	for(int i = t ; i >= 1 ; i -- )
	 cout<<b[i]<<" ";
	return 0;
}

导弹拦截

【问题描述】

某国为了预防敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够达到任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000的正整数,导弹数不超过1000),计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

【输入形式】

一行,输入导弹依次飞来的高度

【输出形式】

共两行,第1行为最多拦截的导弹数,第2行输出要拦截所有导弹最少要配备的系统数

【样例输入】

389 207 155 300 299 170 158 65

【样例输出】

6
2


# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
int n , dp[MAX],a[MAX],len,q[MAX],p[MAX];

int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(cin >> a[++n]);
    n--;
    len = 0;
    q[0] = -inf;
    for(int i = 1 ; i <= n ; i ++ ){
         int l = 0 , r = len ;
		 while(l < r){
		 	int mid = l + r + 1>> 1;
		 	if(q[mid] >= a[i]) l = mid;
		 	 else r = mid - 1;
		 }	
		 q[l + 1] = a[i];
		 len = max(len,l + 1); 
	}
	cout<<len <<"\n";
	
    len = 0;
    p[++len] = a[1]; 
      for(int i = 1 ; i <= n ; i ++){
        int k = 0;
        for(int j = 1 ; j <= len ; j ++)	
		   if(p[j] >= a[i]){
		   	  if(k == 0 ) k = j;
		   	   else if(p[k] > p[j]) k = j;
		   }
		
        if(k == 0 ){
        	 p[++len] = a[i];
		}
		else p[k] = a[i];
	}
	cout<<len;
	return 0;
}

友好城市

【问题描述】

Palmia国有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市。北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同。

每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故。编程帮助政府做出一些批准和拒绝申请的决定,使得在保证任意两条航线不相交的情况下,被批准的申请尽量多。

【输入形式】

第1行,一个整数N(1≤N≤5000),表示城市数。

第2行到第n+1行,每行两个整数,中间用1个空格隔开,分别表示南岸和北岸的一对友好城市的坐标。(0≤xi≤10000)

【输出形式】

仅一行,输出一个整数,表示政府所能批准的最多申请数。

【样例输入】

7

22 4

2 6

10 3

15 12

9 8

17 17

4 2

【样例输出】

4

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
int n,b[MAX],len;
struct Node{
	int x,y;
	bool operator <(const Node &p) const{
		 return x < p.x;
	}
}a[MAX];

int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
	for(int i = 1 ; i <= n ; i ++ ) cin >> a[i].x >> a[i].y ;
	sort(a + 1,a + 1 + n);
	b[++len] = a[1].y ;
	for(int i = 2 ; i <= n ; i++ ){
		int d = upper_bound(b + 1 , b + len + 1,a[i].y) - b;
		b[d] = a[i].y ;
		if(d > len) len++;
	}
	cout<<len;
	return 0;
}

合唱队形

【问题描述】

N位同学站成一排,音乐老师要请其中的(N?K)位同学出列,使得剩下的K位同学排成合唱队形。

合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,…,K他们的身高分别为T1,T2,…,TK,则他们的身高满足T1<T2<…<Ti,Ti>Ti+1>…>TK(1≤i≤K)。

你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。

【输入形式】

输入的第一行是一个整数N(2≤N≤100),表示同学的总数。第二行有n个整数,用空格分隔,第i个整数Ti(130≤Ti≤230)是第i位同学的身高(厘米)。

【输出形式】

输出包括一行,这一行只包含一个整数,就是最少需要几位同学出列。

【样例输入】

8

186 186 150 200 160 130 197 220

【样例输出】

4

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n , a[MAX] , dp1[MAX] , dp2[MAX],ans;


int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1 ; i <= n ; i++) cin >> a[i];
    for(int i = 1 ; i <= n ; i++){
    	dp1[i] = 1;
    	for(int j = 1 ; j < i ; j++)
    	 if(a[i] > a[j]) dp1[i] = max(dp1[i] , dp1[j] + 1);
	}
	
	for(int i = 1 ; i <= n ; i++){
    	dp2[i] = 1;
    	for(int j = 1 ; j < i ; j++)
    	 if(a[i] < a[j]) dp2[i] = max(dp2[i] , max(dp1[j],dp2[j]) + 1);
	}
	
	ans = 0;
	for(int i = 1 ; i <= n ; i++)
	 ans = max(ans,max(dp1[i],dp2[i]));
	cout<<n - ans;
	return 0;
}

最长公共子序列

【问题描述】

一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X= { x1, x2,…, xm},则另一序列Z= {z1, z2,…, zk}是X的子序列是指存在一个严格递增的下标序列 {i1, i2,…, ik},使得对于所有j=1,2,…,k有 Xij=Zj。

例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X= { A, B, C, B, D, A, B}和Y= {B, D, C, A, B, A},则序列{B,C,A}是X和Y的一个公共子序列,序列{B,C,B,A}也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。给定两个序列X= {x1, x2, …, xm}和Y= {y1, y2, … , yn},要求找出X和Y的一个最长公共子序列。

【输入形式】

输入共两行。每行为一个由大写字母构成的长度不超过200的字符串,表示序列X和Y。

【输出形式】

输出第一行为一个非负整数。表示所求得的最长公共子序列的长度。若不存在公共子序列,则输出仅有一行输出一个整数0。

【样例输入】

ABCBDAB

BDCABA

【样例输出】

4

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

char a[MAX],b[MAX];
int n , m;
int dp[205][205];


int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> a + 1 >> b + 1;
    n = strlen(a + 1);
    m = strlen(b + 1);
    for(int i = 1 ; i <= n ; i ++ ){
    	 for(int j = 1 ; j <= m ; j ++ ){
    	 	 dp[i][j] = max(dp[i-1][j] , dp[i][j - 1]  );
    	 	 if(a[i] == b[j])
    	 	  dp[i][j] = max(dp[i][j] , dp[i - 1][j - 1] + 1 );
		 }
	}
	cout<<dp[n][m];
	return 0;
}

机器分配

【问题描述】

总公司拥有高设备M台,准备分给下属的N个分公司。各分公司获得这些设备,可以为国家提供一定的盈利。问:如何分配这M台设备才能使国家得到的盈利最大?求出最大盈利值。其中M<=15,N<=10。分配原则:每个公司有权获得任意数目的设备,但总台数不超过设备数M。

【输入形式】

第1行有两个数,第1个数是分公司数N,第2个数是总设备台数M。接下来是N*M的矩阵,表明了第I个公司分配J台机器的盈利。

【输出形式】

第1行输出最大盈利值,接下来N行,每行2个数,即分公司编号和该公司获得设备台数。

【样例输入】

3 3

30 40 50

20 30 50

20 25 30

【样例输出】

70

1 1

2 1

3 1

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int n , m,dp[2005][2005],a[2005][2005],pre[2005][2005];
void dfs(int x,int y){
	if(x == 0) return;
	dfs(x-1,y-pre[x][y]);
	cout<<x<<" "<<pre[x][y]<<"\n";
}
int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for(int i = 1 ; i <= n ; i++ )
     for(int j = 1 ; j <= m ; j++)
      cin >> a[i][j];
    
    for(int i = 1 ; i <= n ; i++ )
     for(int j = 1 ; j <= m ; j++ )
      for(int k = 0 ; k <= j ; k ++){
      	 if(dp[i][j] <= dp[i-1][j-k] + a[i][k])
      	 {
      	 	dp[i][j] = dp[i-1][j-k] + a[i][k];
      	 	pre[i][j] = k;
		 }
	  }
	  cout<<dp[n][m]<<"\n";
	/*  for(int i = 1 ; i <= n ; i++ ){
	  	for(int j = 1 ; j <= m ; j ++)
	  	 cout<<pre[i][j]<<" ";
	  	 cout<<"\n";
	  	 
	  } */
	  dfs(n,m);
	return 0;
}

砝码称重

【问题描述】

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000g)。

【输入形式】

a1、a2、a3、a4、a5、a6(表示1g砝码有a1个,2g砝码有a2个,…20g砝码有a6个)

【输出形式】

Total=n(n表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)

【样例输入】

1 1 0 0 0 0
【样例输出】

Total=3

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int a[6],c[6]={1,2,3,5,10,20};
int b[MAX],t,m,ans,dp[MAX];
int main(){  
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    dp[0] = 1;
    for(int i = 0 ; i < 6 ; i++){
    	 cin >> a[i];
    	 for(int j = 1 ; j <= a[i] ; j ++ )
    	  b[++t] = c[i] , m += c[i];
	}
	for(int i = 1 ; i <= t ; i++ ){
		 int v = b[i];
		 for(int j = m ; j >= v ; j-- )
		  dp[j] += dp[j - v];
	}
	for(int i = 1 ; i <= m ; i++)
	 if(dp[i]) ans++;
	cout<<"Total="<<ans;
	return 0;
}


装箱问题

【问题描述】

有一个箱子容量为v(正整数,0≤v≤20000),同时有n个物品(0<n≤30),每个物品有一个体积(正整数)。

要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

【输入形式】

箱子的容量v

物品数n

接下来n行,分别表示这n个物品的体积

【输出形式】

箱子剩余空间

【样例输入】

24

6

8

3

12

7

9

7

【样例输出】

0

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<iostream>
# include<algorithm>
# include<cmath>
# include<cstdio>
# include<set>
# include<stack>
# include<queue> 
# include<map>
# include<string>
# include<cstring> 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int MAX=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 

int m ,n , v,dp[MAX];


int main(){  
   std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> m >> n;
    for(int i = 1 ; i <= n ; i ++ ){
    	 cin >> v;
    	 for(int j = m ; j >= v ; j --)
    	  dp[j] = max(dp[j],dp[j - v] + v);
	}
	cout<<m-dp[m];
	return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:53:53  更:2021-07-29 11:55:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:58:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码