题意:给出一个序列,将该序列中的每一个数分别变化ki,使得这个数字成为一个非递减序列,求min( sum( abs ( ki ) ) )
链接:http://codeforces.com/problemset/problem/13/C
思路:先对该序列排序,求通过dp维护变化最少的情况,第一维为第i位的变化情况,第二维为第i位数字变成第j大的数字至少要变化的数量,类似背包将第一维处理成dp[2][n]的数组即可。状态转移方程:dp[cnt][j] = min ( dp[cnt][j-1], dp[cnt^1][j] + abs ( num[i] - tmp[j] ) )
注意点:无
以下为AC代码:
# | Author | Problem | Lang | Verdict | Time | Memory | Sent | Judged |
---|---|---|---|---|---|---|---|---|
9744719 | Practice: luminous11 | 13C - 8 | GNU C++11 | Accepted | 312 ms | 156 KB | 2015-02-07 15:50:41 | 2015-02-07 15:50:41 |
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <deque>
#include <list>
#include <cctype>
#include <algorithm>
#include <climits>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#define ll long long
#define ull unsigned long long
#define all(x) (x).begin(), (x).end()
#define clr(a, v) memset( a , v , sizeof(a) )
#define pb push_back
#define mp make_pair
#define read(f) freopen(f, "r", stdin)
#define write(f) freopen(f, "w", stdout)
using namespace std;
const double pi = acos(-1);
int main()
{
ios::sync_with_stdio( false );
ll num[5006];
ll tmp[5006];
ll dp[2][5006];
ll n;
while ( cin >> n ){
clr ( num, 0 );
clr ( tmp, 0 );
for ( int i = 1; i <= n; i ++ ){
cin >> num[i];
tmp[i] = num[i];
}
sort( tmp + 1, tmp + n + 1 );
clr ( dp[0], 0 );
int cnt = 0;
for ( int i = 1; i <= n; i ++ ){
cnt ^= 1;
clr ( dp[cnt], 0x3f3f3f3f );
for ( int j = 1; j <= n; j ++ ){
dp[cnt][j] = min ( dp[cnt][j-1], dp[cnt^1][j] + abs ( num[i] - tmp[j] ) );
}
}
ll _min = ( 0x3fffffff3fffffff );
for ( int i = 1; i <= n; i ++ ){
_min = min ( _min, dp[cnt][i] );
}
cout << _min << endl;
}
return 0;
}