题目大意:给定n个数a[0],a[1],,,,a[n-1] 现在你要把它变成一个单调的数列 并应此作出修改 value=(a[i]-b[i]),(b[i]是修改后的数) 问value 总和最小是多少
1 ≤ N ≤ 2,000,0 ≤ a[i] ≤ 1,000,000,000;
分析:状态转移方程 dp[i][j]=abs(a[i]-j)+min(dp[i-1][k]); 其中k<=j; j表示修改后的值 ; 初始状态为店铺dp[1][j]=0;
时间复杂度分析:朴素的方法是O(n×m) m为枚举的个数 因为 m的上限就是a[i]的上限所以肯定会超时,有我们考虑到每次修改为a[i] 已有的值时最优, 所以只需把a[i]枚举出来即可 所以时间复杂度就变成了O(n*n) 所以能过;
ac代码:
#include<bits/stdc++.h> using namespace std; int dp[2002][2002]; int road[2002],sort_road[2002]; int main(){ ios::sync_with_stdio(0); cin.tie(0); int n; cin>>n; for(int i=1;i<=n;i++) cin>>road[i],sort_road[i]=road[i]; sort(sort_road+1,sort_road+n+1); for(int i=1;i<=n;i++)dp[1][i]=0; for(int i=2;i<=n;i++){ int mi=0x3f3f3f3f; for(int j=1;j<=n;j++){ mi=min(dp[i-1][j],mi); dp[i][j]=mi+abs(sort_road[j]-road[i]); } } int mi=0x3f3f3f3f; for(int i=1;i<=n;i++) mi=min(dp[n][i],mi); cout<<mi<<endl; }