链接:https://ac.nowcoder.com/acm/contest/5881/C
来源:牛客网
不平衡数组
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一个长度为 n 的数组。要求相临的数大小不相同,假如相临数的相同,
你可以通过将 a[i]+1 来改变它的大小,但是需要付出 b[i]的代价,同时对于每
个 a[i]只能加一次。问你付出的最小代价。
输入描述:
第 1 行 1 个整数 n,表示数组长度为 n
接下来 n 行,每行 2 个正整数 a[i]与 b[i],表示 a 数组中的第 i 个数,以及将第 i 个数+1 的代价。
对于20%的数据,保证b[i] = 1
对于另外10%的数据,保证所有a[i]相等
对于另外10%的数据,保证所有的a[i]不相等
对于100%的数据,1<=n<=2e5,0<=a[i]、b[i]<=1e9
输出描述:
1 行,一个数字 ans,表示最小代价。
示例1
输出
复制2
因为每一位只能加一次,所以比较容易想到dp,用dp[i][0]表示当前位置不加一,dp[i][1]表示当前位置加一,那么我们每次只要关心前后两位在加一或不加的状态下会不会冲突就行了,
不冲突我们就能递推了,具体转移方程如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+10; //f[i][1]代表加 //f[i][0]代表不加 ll a[maxn],b[maxn],f[maxn][2]; int main(){ int n,m; cin>>n; for(int i=1;i<=n;i++){ scanf("%d%d",&a[i],&b[i]); } f[1][1]=b[1]; for(int i=2;i<=n;i++){ if(a[i]==a[i-1]){ f[i][1]=f[i-1][0]+b[i]; f[i][0]=f[i-1][1]; } else{ if(a[i-1]+1==a[i]){ f[i][1]=min(f[i-1][1],f[i-1][0])+b[i]; f[i][0]=f[i-1][0]; } else if(a[i-1]==a[i]+1){ f[i][0]=min(f[i-1][0],f[i-1][1]); f[i][1]=f[i-1][1]+b[i]; } else{ f[i][0]=min(f[i-1][1],f[i-1][0]); f[i][1]=min(f[i-1][1],f[i-1][0])+b[i]; } } } ll ans=min(f[n][0],f[n][1]); printf("%d",ans); }
n = read(); for(int i = 1 ; i <= n ; ++i){ a[i] = read(),b[i] = read(); dp[i][0] = dp[i][1] = INF; } 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]); if (a[i] != (a[i - 1] + 1)) dp[i][0] = min(dp[i][0], dp[i - 1][1]); if ((a[i] + 1) != a[i - 1]) dp[i][1] = min(dp[i][1], dp[i - 1][0] + b[i]); if ((a[i] + 1) != (a[i - 1] + 1)) dp[i][1] = min(dp[i][1], dp[i - 1][1] + b[i]); } ll ans = min(dp[n][0],dp[n][1]);