您的位置:首页 > 运维架构

Topcoder srm 653 div.2 1000 - SingingEasy(区间DP)

2015-03-26 11:19 225 查看
题意:

给出一个序列,请你找出两个没有交且并为全集的子序列,使得每个子序列相邻两位之间的数字差的绝对值之和最小。

思路:

DP....(dp弱渣, 折腾了好久请教了人才会>,<..

dp[i][j] 表示一人最后一个取的位置是i, 一人最后一个取的位置是j.

分两种情况:

1.i-j>1: dp[i][j] = dp[i-1][j] + abs(pitch[i-2]-pitch[i-1]) 让A一直取数..

2.i-j=1: 1) A只取i, 其他的都给B.

              2)A取j, 枚举A上一次取的位置k,B取i, 上一次取k: res = min(res, dp[j][k] + abs(pitch[i-1]-pitch[k-1])) 

                  理解: 两个人会把其中一个位置当做他取的最后一个位置, 那另一个人取的最后一个位置就是最后一个数了. 可以先想比如只有3个人, 这样写是可以把所有的情况涵盖的,相当于问题的子问题.

AC.

#line 7 "SingingEasy.cpp"
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>

using namespace std;

#define PB push_back
#define MP make_pair

#define REP(i,n) for(i=0;i<(n);++i)
#define FOR(i,l,h) for(i=(l);i<=(h);++i)
#define FORD(i,h,l) for(i=(h);i>=(l);--i)

typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long LL;
typedef pair<int,int> PII;

int dp[2005][2005];

class SingingEasy
{
public:
int solve(vector <int> pitch)
{
int len = pitch.size();
if(len <= 2) return 0;

dp[1][0] = 0;
for(int j = 2; j <= len; ++j) {
dp[j][0] = dp[j-1][0] + abs(pitch[j-2]-pitch[j-1]);
}
dp[2][1] = 0;
for(int i = 3; i <= len; ++i) {
for(int j = 1; j < i; ++j) {
if(i - j > 1) {
dp[i][j] = dp[i-1][j] + abs(pitch[i-2]-pitch[i-1]);
}
else {
int res = 1e9+5;
for(int k = 1; k < j; ++k) {
res = min(res, dp[j][k] + abs(pitch[i-1]-pitch[k-1]));
}
dp[i][j] = min(res, dp[j][0]);
}
}
}

int ans = dp[len][0];
for(int i = 1; i < len; ++i) {
ans = min(ans, dp[len][i]);
}
return ans;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Topcoder