Submission #59829

# Submission time Handle Problem Language Result Execution time Memory
59829 2018-07-23T07:39:36 Z model_code Ranklist Sorting (BOI07_sorting) C++
100 / 100
14 ms 8668 KB
// Author:	Adrian Kuegel
// Date: 	January 16th, 2007
// Algorithm:	Dynamic Programming
// Complexity:	O(n^2)

#include <stdio.h>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <map>
using namespace std;
#define prev asdadasd

#define INF 100000000
#define MAXN 1024

typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;

// simulates the sorting process and prints out the moves
// used specifies the numbers which keep their position
// p is the current permutation of the numbers
int simulate(char *used, VI &p) {
	int n = p.size();
	int cost = 0;
	VPII moves;

	for (int i=n-1; i>=0; i--) {
		if (used[i])
			continue;

		// find element i
		VI::iterator it = find(p.begin(),p.end(),i);
		assert(it != p.end());

		int from_pos = distance(p.begin(),it) + 1;
		p.erase(it);

		// find element i+1
		it = find(p.begin(),p.end(),i+1);

		// reinsert i before element i+1
		p.insert(it, i);

		int to_pos = distance(p.begin(),it) + 1;
		cost += from_pos + to_pos;
		moves.push_back(PII(from_pos,to_pos));
	}

	for (int i=0; i<n; i++)
		assert(p[i] == i);

	// print the result
	printf("%d\n",(int)moves.size());
	for (VPII::iterator it=moves.begin(); it!=moves.end(); ++it)
		printf("%d %d\n",it->first,it->second);
	return cost;
}

char used[MAXN+1];
int dp[MAXN+1][MAXN+1],prev[MAXN+1][MAXN+1];

void solve(VI &p) {
	int n = p.size();
	VI pos(n+1);

	p.push_back(n);
	for (int i=0; i<=n; i++)
		pos[p[i]] = i;
	for (int i=0; i<n; i++)
		dp[n][i] = INF;
	dp[n][n] = 0;

	for (int i=n-1; i>=0; --i) {
		int v = 1;

		// determine the current position v, assuming all bigger elements already moved
		// we can only make this assumption because we adjust the costs of not moving an
		// element accordingly (see below)
		for (int j=0; j<pos[i]; ++j)
			if (p[j]<i)
				++v;

		int v2 = 1;
		// move i before element i+1
		// h is the old index position where it moves to
		// v2 is the "real" position where it moves to
		for (int h=0; h<=n; h++) {
			if (p[h] < i)
				++v2;
			dp[i][h] = dp[i+1][h]+v+v2;
			prev[i][h] = h;
		}

		// try to let i at its current position
		// add specifies the additional costs for elements which are skipped
		int add = 0;
		for (int k=pos[i]+1; k<=n; k++) {
			int tcost = dp[i+1][k]+add;
			if (dp[i][pos[i]] > tcost) {
				dp[i][pos[i]] = tcost;
				prev[i][pos[i]] = k;
			}
			if (p[k]<i) {
				// there are i - p[k] elements which will be moved before it
				// since they are all bigger than p[k] they wouldn't be counted
				// when determining the current position
				add += (i-p[k]);
			}
		}
	}

	int mincost = INF,ind = -1;
	for (int i=0; i<=n; i++)
		if (dp[0][i] < mincost) {
			mincost = dp[0][i];
			ind = i;
		}
	assert(ind >= 0);

	// determine which numbers kept their position
	for (int i=0; i<n; ++i) {
		used[i] = (ind == pos[i])?1:0;
		ind = prev[i][ind];
	}
	assert(ind == n);

	used[n] = 1;
	int tcost = simulate(used,p);
	assert(tcost == mincost);
}

int main() {
	int n;
	map<int,int> byscore;

	scanf("%d",&n);
	assert(2 <= n && n <= 1000); // assert valid range for n

	for (int i=0; i<n; ++i) {
		int val;
		scanf("%d",&val);
		assert(val >= 0 && val <= 1000000); // assert valid range
		assert(byscore.find(val) == byscore.end()); // assert distinct scores
		byscore[val] = i;
	}

	int pos = 0; // position counter
	VI p(n); // desired final positions
	for (map<int,int>::reverse_iterator it=byscore.rbegin(); it!=byscore.rend(); ++it,++pos)
		p[it->second] = pos;
	solve(p);
	return 0;
}

Compilation message

sorting.cpp: In function 'int main()':
sorting.cpp:138:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d",&n);
  ~~~~~^~~~~~~~~
sorting.cpp:143:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d",&val);
   ~~~~~^~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 3 ms 376 KB Output is correct
2 Correct 3 ms 488 KB Output is correct
3 Correct 4 ms 524 KB Output is correct
4 Correct 4 ms 812 KB Output is correct
5 Correct 3 ms 1368 KB Output is correct
6 Correct 4 ms 2128 KB Output is correct
7 Correct 9 ms 4512 KB Output is correct
8 Correct 13 ms 6988 KB Output is correct
9 Correct 13 ms 8652 KB Output is correct
10 Correct 14 ms 8668 KB Output is correct