题意
给定一个长度为 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,表示最小代价。
题意
先说一下,这个题目的数据非常的水,很多应该要卡的地方都没有设计数据进行卡,时间也没卡,可以直接暴力$O n*n$就能水过。。。我这里贴一下水的代码,大家就看看就好了。#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5;
int a[MAXN],b[MAXN];
int main(void) {
int n;
cin>>n;
for (int i = 1; i <= n; i++) {
cin>>a[i]>>b[i];
}
int l = 1, r = 2, ans = 0;
while (l <= n) {
while (r <= n && a[l] == a[r]) r++;
if (r - l > 1) {
int sum1 = 0;
for (int j = l; j < r; j += 2) sum1 += b[j];
int sum2 = 0;
for (int j = l + 1; j < r; j += 2) sum2 += b[j];
ans += min(sum1, sum2);
}
l = r; r++;
}
cout<<ans<<endl;
return 0;
}但是我们要正确的做出这个题目我们要考虑几个地方:
1,当连续个a相同的连在一起时,我们要考虑是选择哪些进行加一,就是说我现在的a都相同,那么我们就考虑是选择
还是
进行加一。
2,当出现阶梯状的时,要如何处理,举个例子,这里如果我们
加一了,那么这个时候
和
相同,那么
必定要加一。
考虑到上面情况,我能想到的做法就是使用dp,设dp[n][2],dp[i][0]表示第i个不加一,dp[i][1]表示第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]);
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int n,a[maxn],b[maxn];
#define INF 1e18
ll dp[maxn][2];
int main(void) {
ios::sync_with_stdio(false);
ll n;
cin>>n;
for(int i = 1 ; i <= n ; ++i){
cin>>a[i]>>b[i];
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]);
cout << ans << endl;
return 0;
}

京公网安备 11010502036488号