动态规划
- 确定递推状态: f(n)+解释
- 确定递推公式
- 程序实现
优化:
- 去除冗余状态
- 状态重定义
- 优化转移过程
- 斜率优化
优化-递归+记忆化
if arr[n] return arr[n]递归+记忆化(正向求解-递归) 或 改变求解顺序(逆向递归求解-循环) : 解决效率问题
用long long ,或者更大的:解决数值溢出,不够大问题
HZOJ 38 兔子繁殖问题
- 确定递推状态: f(n)为第n个月的时候兔子的数量
- 确定递推公式: f(1)=1 | f(2)=2 | f(n)=f(n-1)+f(n-2)
- 程序实现
#include <iostream>
using namespace std;
#define MAX_N 100
int digui_jiyihua_arr[MAX_N+5]={
0};
int f(int n){
if(n<=2) return n;
if(digui_jiyihua_arr[n])return digui_jiyihua_arr[n]; //优化-增加记忆点,解决超时问题
digui_jiyihua_arr[n]=f(n-1)+f(n-2);
return digui_jiyihua_arr[n];
}
void acm_1_14_digui_jiyihua_test(){
int n;
cin>>n;
cout << f(n) <<endl;
}
改变求解顺序
从低到高
long long acm_1_14_digui_jiyihua_f[105]={
0};
void acm_1_14_digui_jiyihua_test2(){
int n;
cin>>n;
acm_1_14_digui_jiyihua_f[1]=1;
acm_1_14_digui_jiyihua_f[2]=2;
for(int i=3;i<=n;i++){
acm_1_14_digui_jiyihua_f[i]=acm_1_14_digui_jiyihua_f[i-1]+acm_1_14_digui_jiyihua_f[i-2];
}
cout << acm_1_14_digui_jiyihua_f[n] <<endl;
}
//
// Created by cry on 2024/3/24.
//
#include <vector>
#include <iostream>
using namespace std;
#define MAX_N 100
long long digui_jiyihua_arr[MAX_N+5]={
0};
long long f(int n){
if(n<=2) return n;
if(digui_jiyihua_arr[n])return digui_jiyihua_arr[n]; //优化-增加记忆点,解决超时问题
digui_jiyihua_arr[n]=f(n-1)+f(n-2);
return digui_jiyihua_arr[n];
}
void acm_1_14_digui_jiyihua_test(){
int n;
cin>>n;
cout << f(n) <<endl;
}
//大整数
class BigInt:
public vector<int>{
public:
BigInt()
{
push_back(0);
}
BigInt(int x)
{
this->push_back(x);
process_digit();//处理大整数进位问题
}
//重载+=运算
BigInt &operator+=(const BigInt &a){
for(int i=0;i<a.size();i++){
if(i >= size()) //如果位数超出了
{
push_back(a[i]);
}else at(i)+=a[i];
}
process_digit();
return *this;
}
//重载加法运算
BigInt operator+(const BigInt &a){
BigInt ret(*this);//拷贝一下当前
ret+=a;
return ret;
}
//重载左移运算符
//进位
void process_digit() {
for (int i = 0; i < size(); i++) {
if (at(i) < 10) continue; //当前位置的值小于10,不需要处理
//当前位置的值大于10,就进位
if (i == size() - 1) push_back(0); //增加一位
at(i + 1) += at(i) / 10;
at(i) %= 10;
}
return ;
}
};
// 重写左移运算符
ostream &operator<<(ostream &out,const BigInt &a){
for(int i=a.size()-1;i>=0;i--){
out << a[i];
}
return out;
}
BigInt acm_1_14_digui_jiyihua_f[105]={
0};
void acm_1_14_digui_jiyihua_test2(){
int n;
cin>>n;
acm_1_14_digui_jiyihua_f[1]=1;
acm_1_14_digui_jiyihua_f[2]=2;
for(int i=3;i<=n;i++){
acm_1_14_digui_jiyihua_f[i]=acm_1_14_digui_jiyihua_f[i-1]+acm_1_14_digui_jiyihua_f[i-2];
}
cout << acm_1_14_digui_jiyihua_f[n] <<endl;
}
int main() {
acm_1_14_digui_jiyihua_test2();
return 0;
}
python解法 只需要记忆化就行了,类型不会出问题
#第一代,缺点:效率低 且 数据类型不够大
# dp_1(65) 直接跑不完
def dp_1(n):
if(n<=2):
return n
return dp_1(n-1)+dp_1(n-2)
# 解决:添加记忆化
MAX_N=100
arr=[0]*(MAX_N+5)
def dp_2(n):
if(n<=2):
return n
if arr[n]:return arr[n]
arr[n]=dp_2(n-1)+dp_2(n-2)
return arr[n]
n=int(input())
print(dp_2(n))
# 改变求解顺序
def dp_3(n):
arr=[0]*(MAX_N+5)
if(n<=2):return n
arr[1]=1
arr[2]=2
for i in range(3,n+1):
arr[i]=arr[i-1]+arr[i-2]
return arr[n]
print(dp_3(n))
容斥原理的基本思想
- 在计数的时候为了没有重复 没有遗漏
- 再不考虑重叠的情况,把包含于某内容的所有对象数目先计算出来,然后把计数时重复的计算的数目排斥出去
加多的减掉,减多了加回来
- 结果既无遗漏又无重复—容斥原理
钱币问题

最低0.47元/天 解锁文章
248

被折叠的 条评论
为什么被折叠?



