动态规划c++

动态规划 ,又叫 DP(Dynamic Programming),是在0世纪50年代初,美国数学家 贝尔曼(R.Bellman) 等人在研究多阶段决策过程的优化问题时,提出了著名的最优化原理,从而创立了动态规划。运用在暴力枚举、dfs、bfs、区间最短路等
动态机: 动态机是一种专门做动态规划(DP)的方法,是把DP的每一步都枚举出来两种状态,比如拿小球问题,你要想出拿小球会怎么样,不拿小球会怎么样,从两种方法中求最优解,从而推出公式
这次的题在我的 l u o g u luogu luogu 团队,点击此处跳转

大盗阿福

题目描述

阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。

这条街上一共有 N 家店铺,每家店中都有一些现金。阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。

作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?

输入格式

输入的第一行是一个整数 T (T <= 50) ,表示一共有 T 组数据。

接下来的每组数据,第一行是一个整数 N (1 <= N <= 100, 000) ,表示一共有 N 家店铺。第二行是 N 个被空格分开的正整数,表示每一家店铺中的现金数量。每家店铺中的现金数量均不超过 1000 。

输出格式

对于每组数据,输出一行。该行包含一个整数,表示阿福在不惊动警察的情况下可以得到的现金数量。

样例 #1

样例输入 #1

2
3
1 8 2
4
10 7 6 14

样例输出 #1

8
24

提示

对于第一组样例,阿福选择第 2 家店铺行窃,获得的现金数量为 8 。

对于第二组样例,阿福选择第 1 和 4 家店铺行窃,获得的现金数量为 10 + 14 = 24 。

在这里插入图片描述
这道题说是不能盗窃两个相邻的店铺,所以代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int a[N],dp[N][105];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);	//读入scanf更快
		}
		for(int i=1;i<=n;i++)
		{
			dp[i][0]=max(dp[i-1][1],dp[i-1][0]);	//dp
			dp[i][1]=dp[i-1][0]+a[i];
		}
		printf("%d\n",max(dp[n][1],dp[n][0]));
	}
	return 0;
}

[USACO08FEB] Dining Cows B

题目描述

为了避免餐厅过分拥挤,FJ要求奶牛们分2批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第2批就餐的奶牛排在队尾,队伍的前半部分则由设定为第1批就餐的奶牛占据。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。 第i头奶牛有一张标明她用餐批次D_i(1 <= D_i <= 2)的卡片。虽然所有N头奶牛排成了很整齐的队伍,但谁都看得出来,卡片上的号码是完全杂乱无章的。 在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍,把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个他想要的每个组中的奶牛都站在一起的队列,例如112222或111122。有的时候,FJ会把整个队列弄得只有1组奶牛(比方说,1111或222)。 你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。

输入格式

第1行: 1个整数:N * 第2…N+1行: 第i+1行是1个整数,为第i头奶牛的用餐批次D_i

输出格式

一行: 输出1个整数,为FJ最少要改几头奶牛卡片上的编号,才能让编号变成他设想中的样子。

样例 #1

样例输入 #1

7
2
1
1
1
2
2
1

样例输出 #1

2

样例 #2

样例输入 #2

5
2
2
1
2
2

样例输出 #2

1

提示

1 <= N <= 30000

这道题要的是 全黑 ,或者 全白 ,或者 前面是白,后面是黑 (2是黑,1,是白)
所以代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=30000+10;
int a[N],dp[N][105];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];	//cin也可以
	}
	for(int i=1;i<=n;i++)
	{
		dp[i][1]=dp[i-1][1]+(a[i]==2);	//dp
		dp[i][2]=min(dp[i-1][1],dp[i-1][2])+(a[i]==1);
	}
	cout<<min(dp[n][1],dp[n][2])<<endl;
	return 0;
}

最长上升子序列

题目描述

这是一个简单的动规板子题。

给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n5000) 个不超过 1 0 6 10^6 106 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。

最长上升子序列是指,从原序列中按顺序取出一些数字排在一起,这些数字是逐渐增大的。

输入格式

第一行,一个整数 n n n,表示序列长度。

第二行有 n n n 个整数,表示这个序列。

输出格式

一个整数表示答案。

样例 #1

样例输入 #1

6
1 2 4 1 3 4

样例输出 #1

4

提示

分别取出 1 1 1 2 2 2 3 3 3 4 4 4 即可。
这道题很简单,所以直接亮代码:

#include <bits/stdc++.h>
using namespace std;
const int N=30000+10;
int a[N],dp[N];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		dp[i]=1;
		for(int j=1;j<i;j++)
		{
			if(a[i]>a[j])	//if判断a[i]是否大于a[j],因为for循环的时候已经是j<i就不用在if里判断
			{
				dp[i]=max(dp[i],dp[j]+1);
			}
		}
	}
	int res=0;
	for(int i=1;i<=n;i++)
	{
		res=max(res,dp[i]);
	}
	cout<<res<<endl;
	return 0;
}
电路布线动态规划(Circuit Routing with Dynamic Programming)通常用于解决电子电路设计中的布线优化问题。这个问题可以通过贪心算法动态规划来解决,其中动态规划更为精确。以下是一个简单的动态规划C++代码示例,假设我们要找到从起点到终点的最短路径,每个节点都有两种可能的连接(A和B),每条线路都有成本: ```cpp #include <vector> #include <climits> // 定义状态转移方程,dp[i][j]表示从节点i到节点j的最低成本 int dp[graphSize][graphSize]; // 动态规划函数 int circuitRouting(int start, int end, std::vector<std::vector<int>>& graph) { // 初始化边界条件 for (int i = 0; i <= end; ++i) { dp[start][i] = graph[start][i]; dp[i][end] = graph[i][end]; } // 从左到右填充动态规划表 for (int i = 1; i < graphSize; ++i) { for (int j = 0; j < i; ++j) { dp[i][j] = INT_MAX; // 假设一开始没有路径,所以设为最大值 if (i != end && j != start) { // 避免自环 dp[i][j] = std::min(dp[i][j], dp[j][end] + graph[i][j]); // 选择当前节点到终点的成本加上从j到i的成本 dp[j][i] = dp[i][j]; // 对称性,因为线路可以双向铺设 } } } return dp[end][start]; // 返回从起点到终点的最低成本 } // 示例用法 int main() { int n = 5; // 节点数量 std::vector<std::vector<int>> graph(n, std::vector<int>(n, INT_MAX)); // 初始化一个全0的图,实际应用中根据电路连接情况填充 // 填充实际的线路成本 graph = 3; graph = 2; graph = 1; graph = 4; int start = 0, end = 4; // 起点和终点 int result = circuitRouting(start, end, graph); if (result != INT_MAX) { std::cout << "Minimum cost to route from " << start << " to " << end << " is: " << result << std::endl; } else { std::cout << "No path found." << std::endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值