不平衡数组
题目描述: 给定一个长度为 n 的数组。要求相临的数大小不相同,假如相临数的相同,你可以通过将 a[i]+1 来改变它的大小,但是需要付出 b[i]的代价,同时对于每个 a[i]只能加一次。问你付出的最小代价。
对于100%的数据,1<=n<=2e5,0<=a[i]、b[i]<=1e9
思路 : 每个位置有两个状态 (+1 或 不+1) , 所以直接DP转移状态就好了;
集合表示 : dp[ i ][ j ] 表示前 i 个数里使相邻的数不相等时所花费的最小代价; 当 j = 0 时表示第 i 位不+1, j = 1 时表示第 i 位+1 ;
集合划分 : 根据相邻两个数是否相等 , 以及+1后与相邻的数的关系分为四种情况进行状态转移 ;
Code1 :
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int a[N],b[N];
long long dp[N][2];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
for(int i=1;i<=n;i++){
if(a[i-1]==a[i]){
dp[i][0] = dp[i-1][1]; //相邻两个只能有一个+1
dp[i][1] = dp[i-1][0] + b[i];
}
else if(a[i-1]+1==a[i]){
dp[i][0] = dp[i-1][0]; //i位不加,i-1位就不能加
dp[i][1] = min(dp[i-1][0],dp[i-1][1]) + b[i]; //i位加,i-1位可加可不加
}
else if(a[i-1]==a[i]+1){
dp[i][0] = min(dp[i-1][0],dp[i-1][1]); //i位不加,i-1位可加可不加
dp[i][1] = dp[i-1][1] + b[i]; //i位加,i-1位就得加
}
else {
dp[i][0] = min(dp[i-1][0],dp[i-1][1]); // i位与i-1位 加和不加互不影响
dp[i][1] = min(dp[i-1][0],dp[i-1][1]) + b[i];
}
}
cout<<min(dp[n][1],dp[n][0])<<endl; //取第n位加和不加的最小值
return 0;
}
Code2 :
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int a[N],b[N];
long long dp[N][2];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
memset(dp,0x3f,sizeof dp);
dp[1][0] = 0,dp[1][1] = b[1];
for(int i = 2;i <= n; i ++){ //当每种情况下不相等时即可转移;
if (a[i] != a[i-1]) dp[i][0] = min(dp[i][0],dp[i-1][0]); //i不加,i-1不加
if (a[i] != a[i-1]+1) dp[i][0] = min(dp[i][0],dp[i-1][1]); //i不加,i-1加
if (a[i]+1 != a[i-1]) dp[i][1] = min(dp[i][1],dp[i-1][0]+b[i]); //i加,i-1不加
if (a[i]+1 != a[i-1]+1) dp[i][1] = min(dp[i][1],dp[i-1][1]+b[i]); //i加,i-1加
}
cout<<min(dp[n][1],dp[n][0])<<endl;
return 0;
}