SRM 627 D2L3: BubbleSortWithReversals, dp, 冒泡排序

题目:http://community.topcoder.com/stat?c=problem_statement&pm=13256&rd=16008

参考:http://apps.topcoder.com/wiki/display/tc/SRM+627

首先要知道冒泡排序的swap次数怎样计算:等于 当 i < j  时,A[i] > A[j] 的 有序对(i, j)的数量。f(x ,p) 表示 "位置x及x之后在最大可以交换p次的情况下对swap的最小贡献数“,则对x位置的处理有两种情况,一是x位置不是reversal的一部分,则 f(x, p) = f(x + 1, p),二是x位置是一个reversal左端端点位置,则可以遍历右端端点位置y(取x+1 到 N - 1 ),则f(x, p) = min(位置x到yreverse后对swap的贡献 + f(y + 1, p -1) )。

代码:

#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <iostream>
#include <sstream>
#include <iomanip>

#include <bitset>
#include <string>
#include <vector>
#include <stack>
#include <deque>
#include <queue>
#include <set>
#include <map>

#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <ctime>
#include <climits>
using namespace std;

#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)
typedef pair<int, int> pii;
typedef long long llong;
typedef pair<llong, llong> pll;
#define mkp make_pair
#define FOREACH(it, X) for(__typeof((X).begin()) it = (X).begin(); it != (X).end(); ++it)

/*************** Program Begin **********************/
int dp[51][51];
int xpairs[51]; 	// x位置对swap的贡献数
int revpairs[51][51]; 	// 保存位置x到y reverse后这些位置对swap的贡献数
class BubbleSortWithReversals {
public:
	int N, K;
	int rec(int x, int p) 		// x及x之后位置在最大可以交换p次的情况下对swap的最小贡献数
	{
		if (N == x) {
			return 0;
		}
		int & res = dp[x][p];
		if (-1 != res) {
			return res;
		}
		// position x is not a reversal
		res = xpairs[x] + rec(x + 1, p);	

		// position x is the begin of a reversal
		if (p > 0) {
			for (int y = x + 1; y < N; y++) { 	// right end of reversal
				res = min(res, revpairs[x][y] + rec(y + 1, p - 1));	
			}
		}
		return res;
	}
	int getMinSwaps(vector <int> A, int K) {
		int res = 0;
		this->N = A.size();
		this->K = K;
		memset(xpairs, 0, sizeof(xpairs));
		memset(revpairs, 0, sizeof(revpairs));
		memset(dp, -1, sizeof(dp));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < i; j++) {
				if (A[j] > A[i]) {
					++xpairs[i];
				}
			}
		}
		for (int x = 0; x < N; x++) {
			for (int y = x + 1; y < N; y++) {
				for (int i = x; i <= y; i++) {
					for (int j = 0; j < x; j++) {
						if (A[j] > A[i]) {
							++revpairs[x][y];
						}
					}
					for (int j = i + 1; j <= y ; j++) {
						if (A[j] > A[i]) {
							++revpairs[x][y];	
						}
					}
				}
			}
		}
		res = rec(0, K);
		return res;
	}

};

/************** Program End ************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值