題目描述
蒜頭君的花園裏有 n個花盆,每個花盆可以種一株花,現在花椰妹給了蒜頭君三種花的方案
但是花椰妹的每種方案種的都是同一種花,只是形狀不同
全部種 A 花,第 i 盆花的價格爲 ai
全部種 B 花,第 i 盆花的價格爲 bi
全部種 C 花,第 i 盆花的價格爲 ci
可是蒜頭君覺得整個花園都是同一種花不好看,但是他又不想浪費了花椰妹的好意,
所以他決定依舊是按照花椰妹的方案來買花,也就是說第 ii 盆花只有三個選項:ai,bi,ci , 但是他希望相鄰的兩盆花不是同一種花,
所以他希望你可以幫他計算一下,最少需要花多少錢?
分析題目
題解1:
觀察這道題,發現問題是要求最少需要花多少錢,所以可以使用動態規劃算法
動態方程其實就是求出走到第i步怎樣排列才能花費最小
所以要定義二維數組循環=n次,每次記錄兩種方案(除自己外其他的兩種)可得的值,最後比較找出其中最少的那種方案
代碼如下
#include<iostream>
using namespace std;
int a[3][100100];
int dp[3][100100];
int main(){
int n;
cin >> n;
//初始狀態
for(int i=0;i<3;i++){
for(int j=0;j<n;j++){
cin >> a[i][j];
dp[i][j]=a[i][j];
}
}
for(int j=1;j<n;j++){
for(int i=0;i<3;i++){
int row=i;
int col=j;
int data1=0,data2=0;
if(row==0){
data1=dp[1][col-1];
data2=dp[2][col-1];
}else if(row==1){
data1=dp[0][col-1];
data2=dp[2][col-1];
}else if(row==2){
data1=dp[0][col-1];
data2=dp[1][col-1];
}
dp[row][col]=min(dp[row][col]+data1,dp[row][col]+data2);
}
}
//找到最小值
int Min=min(dp[0][n-1],min(dp[1][n-1],dp[2][n-1]));
cout<<Min<<endl;
return 0;
}
題解2
三種方案,不斷找解,這一步的決定由上一步影響---->>>遞歸/回溯
但注意:
這種解拿不了滿分
注意點:
1.要找的是最小值
2.設置第0步,這樣第一步纔有三種走法
3.定義數組來存儲上一步的選擇
代碼如下
#include <bits/stdc++.h>
using namespace std;
int a[3][10001];
int n;
long long ans = 10000000;
int text[100001];
void dfs(int step,long long sum){
if(sum>=ans){
return;
}
if(step==n){
ans=min(ans,sum);
return;
}
for(int i=0;i<3;i++){
if(step==0){
text[step]=i;
dfs(step+1,sum+a[i][step]);
}else if(text[step-1]!=i){
text[step]=i;
dfs(step+1,sum+a[i][step]);
}
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[0][i];
}
for(int i=0;i<n;i++){
cin>>a[1][i];
}
for(int i=0;i<n;i++){
cin>>a[2][i];
}
dfs(0,0);
cout<<ans<<endl;
return 0;
}
總結
1.遞歸方面:遞歸中如果return不是終止條件,那其和回溯的作用是一樣的
2.面對最值問題,我們一般都選擇的是動態規劃
3.動態規劃中的動態方程。一定要跟題意來