题目描述
蒜头君的花园里有 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.动态规划中的动态方程。一定要跟题意来