- 编程
2024暑假动态规划
- 2024-7-15 16:52:58 @
fibo 常规递归写法
#include <iostream>
using namespace std;
int fibo(int n ){
if (n == 1 || n == 2 ){
return 1;
}
// fibo(n)
return fibo(n-1) + fibo(n-2);
}
int main(){
int n = 40;
cout << " 第 "<< n << " 个月有兔子数为:" << fibo(n);
return 0;
}
fibo 记忆化递归
#include <iostream>
using namespace std;
typedef long long ll;
ll memo[100];
ll fibo(int n , ll memo[] ){
if (n == 1 || n == 2 ){
memo[n] = 1;
return 1;
}
// fibo(n)
if (memo[n] != 0 ) {
return memo[n];
}
else{
memo[n] = fibo(n-1,memo) + fibo(n-2,memo);
return memo[n];
}
}
int main(){
int n = 50;
cout << " 第 "<< n << " 个月有兔子数为:" << fibo(n, memo) << endl;
for(int m : memo){
cout << m << " ";
}
return 0;
}
建议写法
#include <bits/stdc++.h>
using namespace std;
int memo[100];
int fibo(int n, int memo[]){
// 递归退出条件 f0, f1
if(n==0 ){
memo[n] = 0;
return memo[n];
}
if(n== 1){
memo[n] = 1;
return memo[n];
}
// 是否已经记忆
// n != 0 易错
if(memo[n] != 0){
return memo[n];
}
memo[n] = fibo(n-1,memo) + fibo(n-2,memo);
return memo[n];
}
int main(){
int n = 5; // n < 10000
cout << fibo(n,memo) << endl;
for(int x : memo) cout << x << " ";
return 0;
}
递推
#include <bits/stdc++.h>
using namespace std;
int memo[105] ; // 便笺,用来记忆计算后的数值
void fibo(int n , int memo[]){
// 初始化 初始条件即f0,f1
memo[0] = 0; // f0
memo[1] = 1; // f1
for(int i = 2 ; i <n; i ++){
memo[i] = memo[i-1] + memo[i-2];
}
}
int main(){
int n = 6;
// 递推 数组初始化
fibo(100,memo); // 跑一遍数据
for(int x : memo ) cout << x << " ";
// cout << memo[n];
return 0;
}
硬币找零
记快化递归
#include <iostream>
#include <algorithm>
using namespace std;
int memo[100];
int go(int change,int memo[]){
// 退出条件
if(change == 0) return 0;
if(change < 0 ) return -1;
// 搜索 memo,是否已经计算过
if(memo[change] != 0) return memo[change];
int minN = 10000;
// change = 6
if(change >= 5){
minN = min(minN , 1 + go(change - 5,memo));
memo[change] = minN;
}
if(change >= 2){
minN = min(minN , 1+ go(change - 2,memo));
memo[change] = minN;
}
if(change >= 1){
minN = min(minN , 1+ go(change - 1,memo));
memo[change] = minN;
}
return memo[change];
}
int main(){
cout << go(100,memo) << endl;
for(int x : memo) cout << x << " ";
return 0 ;
}
递推
#include <iostream>
using namespace std;
//moneyChange
const int N = 100;
int coins[3] = {5,2,1};
int memo[N] = {0};
int coinChange(int amount){
memo[0]=0;
for(int i = 1; i < N; i++){
memo[i] = -1;
}
for(int change=1;change<=amount;change++){
for(int j=0;j<3;j++){
if(coins[j]<=change&&memo[change-coins[j]]!=-1){
//如果当前金额还未计算或者memo[i]比正在计算的解大,则更新最优解memo[i]
if(memo[change]==-1||memo[change]>memo[change-coins[j]]+1)
memo[change]=memo[change-coins[j]]+1;
}
}
}
return memo[amount]; //返回金额amount的最优解
}
int main(){
cout << coinChange(18);
return 0;
}
记忆式递归(不定数硬币面额)
#include <bits/stdc++.h>
using namespace std;
int coins[10] ; // 硬币面额
int num = 0; // 硬币数量
int memo[20]; // 记录找零的硬币数,下标对应change
int mec(int change,int memo[]){
// 递归退出条件
if(change == 0 ) return 0;
if(change < 0 ) return -1;
// 重复内容
int minN = 1000; // 当前的最小硬币数
// 已经被记录,直接返回
if(memo[change] != 0) return memo[change];
// 排除以上情况,开始计算并存入 memo
// 考虑不同面额产生最优解
for(int i = 0 ; i < num; i++){
if(change >= coins[i]){
//cout << "change:" << coins[i] << endl;
int tmp = 1 + mec(change - coins[i],memo);
//cout << "tmp:" << tmp <<endl;
minN = min(minN , tmp);
}
// 更新当前面额最优解
memo[change] = minN;
}
return memo[change];
}
int main(){
int change;
cin >> change;
while(1){
cin >> coins[num ++];
if(getchar() == '\n') break;
}
cout << mec(18,memo) << "个硬币\n";
// for(int x : coins ) cout << x << " ";
// cout << endl;
// for(int x : memo) cout << x << " ";
// cout << endl;
return 0;
}
递推(不限硬币面额)
#include <bits/stdc++.h>
using namespace std;
int coins[10] ; // 硬币面额
int num = 0; // 硬币数量
const int MN = 20;
int memo[MN]; // 记录找零的硬币数,下标对应change
void mec(int change,int memo[]){
memo[0] = 0 ;
// 初始化 memo 的状态
for(int i = 1; i < change; i++){
memo[i] = -1;
}
for(int k = 0 ; k < change ; k++){
for(int j = 0 ; j < num ; j++){
if(k >= coins[j]){
int tmp = 1+ memo[k - coins[j]];
if(memo[k]==-1 ) // 没有被计算过
memo[k]=tmp;
if(tmp < memo[k]) // 新的兑换方式比当前的更优
memo[k]=tmp;
}
}
}
}
int main(){
int change;
cin >> change;
while(1){
cin >> coins[num ++];
if(getchar() == '\n') break;
}
mec(20,memo);
for(int x : memo) cout << x << " ";
// cout << memo[6];
return 0;
}
走格子
动态规划(无限制条件)
#include <iostream>
using namespace std;
const int N = 11;
int dp[N][N];
void go(){
for(int i = 1 ; i < N;i++){
for(int j = 1; j < N ; j++){
if(i== 1 || j == 1) {
dp[i][j] = 1;
}else{
dp[i][j] = dp[i][j-1] + dp[i-1][j];
//cout << "dp[" << i << "][" << j << "] = " << dp[i][j] << endl;
}
}
}
}
int main(){
go();
cout << dp[3][3];
return 0;
}
最小路径和
#include <bits/stdc++.h>
using namespace std;
const int N = 20;
int dp[N][N]={0};
int grid[N][N];
void go(int n,int m){
// dp[0][0] = 0;
for(int i = 1 ; i <= n; i++){
dp[i][1] = dp[i-1][1] + grid[i][1];
}
for(int j = 1 ; j <= m; j++){
dp[1][j] = dp[1][j-1] + grid[1][j];
}
for(int i = 2 ; i <= n; i++){
for(int j = 2 ; j <= m ; j++){
dp[i][j] = min( dp[i-1][j] , dp[i][j-1] )
+ grid[i][j];
}
}
}
int main(){
int n , m ;
cin >> n >> m;
for(int i = 1 ; i <= n; i++){
for(int j = 1 ; j <= m ; j++){
cin >> grid[i][j];
}
}
go(n,m);
cout << dp[n][m];
// for(int i = 1 ; i <= n; i++){
// for(int j = 1 ; j <= m ; j++){
// printf("dp[%d][%d] = %d \n",i,j,dp[i][j]);
// }
// }
return 0;
}
背包问题
01 背包
#include <iostream>
using namespace std;
int v[4] = {0,1500,3000,2000};
int w[4] = {0,1 ,4 ,3 }; // 最大值为 4 斤,所以下面的循环为 j<=4
const int N = 20;
int dp[N][N] = {0};
void go(){
// 初始化 0 行 0 列为 0 ,通过数组定义为全局变量,实现 赋值为 0
for(int i = 1; i <=3; i ++ ) { // i: 物品
for(int j = 1; j <= 4 ; j++){ // j: 容量
if(j >= w[i]){
int tmp = v[i] + dp[i-1][j-w[i]];
dp[i][j] = max(tmp,dp[i-1][j]);
}else{
dp[i][j] = dp[i-1][j];
}
}
}
}
int main(){
go();
cout << "dp[3][3] : " << dp[3][3] << endl;
cout << "dp[3][4] : " << dp[3][4] << endl;
return 0;
}
https://ok.hn.cn/p/T1267
题解:
#include <bits/stdc++.h>
using namespace std;
int w[35] = {0}; // 物品重量
int c[35] = {0}; // 物品价值
int dp[35][205]={0};
int d1[205] = {0};
int main(){
int m,n;
cin >> m >> n;
for(int i = 1 ; i <= n;i++){
cin >> w[i] >> c[i];
}
for(int i = 1 ; i<=n; i++){ //物品
for(int j = 1; j <= m ; j++){ // 容量
if(j >= w[i]){
dp[i][j] = max(dp[i-1][j], c[i] + dp[i-1][j-w[i]] );
}else{ // 不偷
dp[i][j] = dp[i-1][j];
}
}
// 滚动数组
for(int k = m ; k >= w[i] ; --k){
// dp[j] = max(dp[j], dp[j-w[i]]+c[i]);
d1[k] = max(d1[k], c[i] + d1[k-w[i]] );
}
}
// cout << dp[m][n] << endl;
cout << dp[n][m] << endl;
cout << d1[m] << endl;
for(int x : d1) cout << x << " ";
return 0;
}
10 条评论
-
symo LV 10 MOD @ 2024-7-24 13:43:29
-
2024-7-21 15:45:26@
#include <bits/stdc++.h> using namespace std; const int N=20; int dp[N][N]; int grid[N][N]; int n,m; void go(){ for(int i=1;i<=n;i++){ dp[i][1]=dp[i-1][1]+grid[i][1]; } for(int j=1;j<=m;j++){ dp[1][j]=dp[1][j-1]+grid[1][j]; } for(int i=2;i<=n;i++){ for(int j=2;j<=m;j++){ dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j]; } } } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>grid[i][j]; } } go(); cout<<dp[n][m]; return 0; }
-
2024-7-19 17:12:01@
#include <bits/stdc++.h> using namespace std; int dp[50][50]; void go(){ for(int i=1;i<50;i++){ for(int j=1;j<50;j++){ if(i==1||j==1){ dp[i][j]=1; } else{ dp[i][j]=dp[i-1][j]+dp[i][j-1]; } } } } int main(){ int n,m; cin>>n>>m; go(); cout<<dp[n][m]; return 0; }
-
2024-7-17 19:48:27@
#include <iostream> using namespace std; int memo[100]={0,1}; int may(int ch ,int memo[]){ int count =1000; if(ch==0)return 0; if(ch<=-1)return 0; if(ch>=5) memo[ch]=min(count,may(ch-5,memo)+1) ; if(ch>=2) memo[ch]=min(count,may(ch-2,memo)+1) ; if(ch>=1) memo[ch]=min(count,may(ch-1,memo)+1) ; return memo[ch]; } int main(){ int ch =20; cout <<may(ch,memo); return 0; }
-
2024-7-17 18:23:56@
#include <iostream> using namespace std; int memo[100]={0,1}; int fibo(int n,int memo[]){ if (n==0)return 0; if (n==1)return 1; if (memo[n]!=0){ return memo[n]; }else{ memo[n]=fibo(n-1,memo)+fibo(n-2,memo); } return memo[n]; } int main(){ int n=20; cout<<fibo(n,memo); return 0; }
-
2024-7-17 17:48:22@
#include <bits/stdc++.h> using namespace std; int memo[100]; int fibo(int n,int memo[]){ if(n==1||n==2){ memo[n]=1; return 1; } if(memo[n]!=0){ return memo[n]; } else{ memo[n]=fibo(n-1,memo)+fibo(n-2,memo); return memo[n]; } } int main(){ int n; cin>>n; cout<<fibo(n,memo); return 0; }
-
2024-7-15 17:24:20@
#include using namespace std; typedef long long ll;
ll memo[100];
ll fibo(int n , ll memo[] ){ if (n == 1 || n == 2 ){ memo[n] = 1; return 1; } // fibo(n) if (memo[n] != 0 ) { return memo[n]; } else{ memo[n] = fibo(n-1,memo) + fibo(n-2,memo); return memo[n]; } }
int main(){ int n = 50; cout << " 第 "<< n << " 个月有兔子数为:" << fibo(n, memo) << endl; for(int m : memo){ cout << m << " "; } return 0; }
-
2024-7-15 17:23:39@
#include <bits/stdc++.h> using namespace std; long long memo[100]; long long fibo(int n,long long memo[]){ if(n==1||n==2){ memo[n]=1; return 1; } if(memo[n] != 0){ return memo[n]; } else{ memo[n]=fibo(n-1,memo)+fibo(n-2,memo); return memo[n]; } return 0; } int main(){ int n=10; cout<<"第"<<n<<"个月有兔子树为:"<<fibo(n,memo); return 0; }
-
2024-7-15 16:54:45@
#include <iostream> using namespace std; int fibo(int n){ if (n==1|| n==2){ return 1; } return fibo(n-1)+fibo(n-2); return 0; } int main(){ int n=40; cout<<"第"<<n<<"个月有兔子数为:"<<fibo(n); return 0; }
-
2024-7-15 16:54:16@
#include using namespace std; int fibo(int n ){ if (n == 1 || n == 2 ){ return 1; } // fibo(n) return fibo(n-1) + fibo(n-2); }
int main(){ int n = 40; cout << " 第 "<< n << " 个月有兔子数为:" << fibo(n); return 0; }
- 1