您的位置:首页 > 其它

srm 653 div2 1000(dp)

2015-03-17 22:36 381 查看
题意:

一个序列的值定义为其差分结果的绝对值之和。例如, {1, 2, 3} 值为 abs(2-1) + abs(3-2) = 2

现在有一个长度大于等于1的序列,要求把它分成两个子序列,使得两个序列的值之和最小。

思路:

一开始想残了。。

打算用f[A唱最后一个音][B唱的最后一个音]f[A唱最后一个音][B唱的最后一个音]这个状态,显然这是个n3的复杂度。。。

其实,我们只要考虑f[i][j],i<jf[i][j], i的情况就行了。。。

状态转移:

1)j继续唱, f[i][j]=f[i][j−1]+abs(v[j]−v[j−1]),i<j−1f[i][j] = f[i][j-1] + abs(v[j] - v[j-1]), i

2)j打断i, f[i][j]=f[k][i−1]+abs(v[j]−v[k]),i=j−1,k<if[i][j] =f[k][i-1] + abs(v[j] - v[k]), i=j-1, k

2的情况注意k=0,这个时候转移是不产生额外费用的。

const int Maxn = 2000;
const int inf = INT_MAX/2;
int dp[Maxn+5][Maxn+5];

class SingingEasy
{
public:
int solve(vector <int> pitch)
{
int n = pitch.size();
dp[0][1] = 0;
for (int i=2;i<=n;++i) {
for (int j=0;j<i-1;++j) {
dp[j][i] = dp[j][i-1] + abs (pitch[i-1] - pitch[i-2]);
}
dp[i-1][i] = inf;
for (int k = 0;k<i-1;++k) {
int tmp = k == 0 ? 0 : abs(pitch[i-1] - pitch[k-1]);
if (dp[k][i-1] + tmp < dp[i-1][i]) dp[i-1][i] = dp[k][i-1] + tmp;
}
}
int ans = inf;
for (int i=0;i<n;++i) ans = min (ans, dp[i]
);
return ans;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: