제출 #301413

#제출 시각아이디문제언어결과실행 시간메모리
301413Khongor카니발 티켓 (IOI20_tickets)C++14
11 / 100
3081 ms1792 KiB
#include "tickets.h"
#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> ans;

// 1 5
// 10 10
// 8 12
// 12 20

// a1 a2 b1 c1
// b2 c2 d1 d2

// -a1 -b1 -c1 d2
// -a1 -b1 +c2 +d2

vector<vector<int>> p;
vector<vector<bool>> used;
long long bst;

void rec(int k, int at, vector<vector<int>> &x) {
	if (at == p.size()) {
		vector<int> v;
		for (int i = 0; i < p.size(); i++) {
			for (auto idx: p[i]) {
				v.push_back(idx);
			}
		}
		sort(v.begin(), v.end());
		long long cur = 0;
		for (int i = 0; i < v.size() / 2; i++)
			cur += v[v.size() - 1 - i] - v[i];
		bst = max(bst, cur);
		return;
	}
	if (p[at].size() == k) {
		rec(k, at + 1, x);
		return;
	}
	for (int i = 0; i < x[at].size(); i++)
		if (!used[at][i]) {
			used[at][i] = true;
			p[at].push_back(x[at][i]);
			rec(k, at, x);
			p[at].pop_back();
			used[at][i] = false;
		}
}

long long slow(int k, vector<vector<int>> x) {
	int n = x.size();
	int m = x[0].size();
	p = vector<vector<int>>(n);
	used = vector<vector<bool>>(n, vector<bool>(m, false));
	bst = -1;
	rec(k, 0, x);
	return bst;
}

long long fast(int k, vector<vector<int>> x) {
	int n = x.size();
	int m = x[0].size();
	ans = vector<vector<int>>(n, vector<int>(m, -1));

	long long res = 0;
	vector<pair<int, pair<int, int>>> all;
	bool binary = true;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			all.push_back({x[i][j], {i, j}});
			if (x[i][j] > 1) binary = false;
		}
	sort(all.begin(), all.end());
	vector<vector<pair<int, int>>> high(n), pickedLow(n), pickedHigh(n);
	int median = (all[n * m / 2].first + all[n * m / 2 - 1].first) / 2;

	int cnt = 0;
	for (int i = 0; i < all.size(); i++) {
		int color = all[i].second.first;
		int ticket = all[i].second.second;
		if (i < all.size() / 2) {
			if (pickedLow[color].size() < k) {
				pickedLow[color].push_back({median - all[i].first, ticket});
				cnt++;
				res += median - all[i].first;
			}
		} else {
			high[color].push_back({all[i].first - median, ticket});
		}
	}
	for (int i = 0; i < n; i++) {
		while (pickedLow[i].size() + pickedHigh[i].size() < k) {
			res += high[i].back().first;
			pickedHigh[i].push_back(high[i].back());
			high[i].pop_back();
		}
	}

	vector<vector<long long>> b(n);
	int need = cnt - n * k / 2;
	for (int i = 0; i < n; i++) {
		long long s = 0;
		b[i].push_back(0);
		for (int j = 1; j <= min(pickedLow[i].size(), high[i].size()); j++) {
			s += high[i][high[i].size() - j].first - pickedLow[i][pickedLow[i].size() - j].first;
			b[i].push_back(s);
		}
	}

	long long inf = -(1LL << 62);
	vector<vector<long long>> dp(n + 1, vector<long long>(need + 1, inf));
	dp[0][0] = 0;
	vector<vector<int>> back(n + 1, vector<int>(need + 1));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j <= need; j++) {
			if (dp[i][j] == inf) continue;
			for (int k = 0; k < b[i].size(); k++) {
				if (j + k > need) break;
				if (dp[i][j] + b[i][k] > dp[i + 1][k + j]) {
					dp[i + 1][k + j] = dp[i][j] + b[i][k];
					back[i + 1][k + j] = k;
				}
			}
		}
	}
	res += dp[n][need];

	for (int i = n - 1; i >= 0; i--) {
		int k = back[i + 1][need];
		need -= k;
		for (int j = 0; j < k; j++) {
			pickedLow[i].pop_back();
			pickedHigh[i].push_back(high[i].back());
			high[i].pop_back();
		}
	}

	// vector<int> at(n, 0);
	// while (need--) {
	// 	int idx = -1, best = 0;
	// 	for (int i = 0; i < n; i++) {
	// 		if (at[i] == b[i].size()) continue;
	// 		int cur;
	// 		cur = b[i][at[i]];

	// 		if (idx == -1 || cur > best) {
	// 			best = cur;
	// 			idx = i;
	// 		}
	// 	}

	// 	assert(idx != -1);

	// 	// switch
	// 	res += best;
	// 	at[idx]++;
	// 	pickedLow[idx].pop_back();
	// 	pickedHigh[idx].push_back(high[idx].back());
	// 	high[idx].pop_back();
	// }

	// construct
	for (int r = 0; r < k; r++) {
		vector<bool> used(n);
		vector<pair<int, int>> counts;
		for (int i = 0; i < n; i++) counts.push_back({pickedLow[i].size(), i});
		sort(counts.rbegin(), counts.rend());

		int taken = 0;
		for (int ii = 0; ii < n; ii++) {
			int i = counts[ii].second;
			if (pickedLow[i].size() > 0) {
				used[i] = true;
				taken++;
				ans[i][pickedLow[i].back().second] = r;
				pickedLow[i].pop_back();
			}
			if (taken == n / 2) break;
		}
		taken = 0;
		for (int i = 0; i < n; i++) {
			if (pickedHigh[i].size() > 0 && !used[i]) {
				taken++;
				ans[i][pickedHigh[i].back().second] = r;
				pickedHigh[i].pop_back();
			}
			if (taken == n / 2) break;
		}
	}

	allocate_tickets(ans);
	long long sl = slow(k, x);
	assert(sl >= res);
	return sl;
}

long long find_maximum(int k, std::vector<std::vector<int>> x) {
	return fast(k, x);
}

// a b a c
// c b d d

컴파일 시 표준 에러 (stderr) 메시지

tickets.cpp: In function 'void rec(int, int, std::vector<std::vector<int> >&)':
tickets.cpp:23:9: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   23 |  if (at == p.size()) {
      |      ~~~^~~~~~~~~~~
tickets.cpp:25:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   25 |   for (int i = 0; i < p.size(); i++) {
      |                   ~~^~~~~~~~~~
tickets.cpp:32:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   32 |   for (int i = 0; i < v.size() / 2; i++)
      |                   ~~^~~~~~~~~~~~~~
tickets.cpp:37:19: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   37 |  if (p[at].size() == k) {
      |      ~~~~~~~~~~~~~^~~~
tickets.cpp:41:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   41 |  for (int i = 0; i < x[at].size(); i++)
      |                  ~~^~~~~~~~~~~~~~
tickets.cpp: In function 'long long int fast(int, std::vector<std::vector<int> >)':
tickets.cpp:79:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   79 |  for (int i = 0; i < all.size(); i++) {
      |                  ~~^~~~~~~~~~~~
tickets.cpp:82:9: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, std::pair<int, int> > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   82 |   if (i < all.size() / 2) {
      |       ~~^~~~~~~~~~~~~~~~
tickets.cpp:83:32: warning: comparison of integer expressions of different signedness: 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   83 |    if (pickedLow[color].size() < k) {
      |        ~~~~~~~~~~~~~~~~~~~~~~~~^~~
tickets.cpp:93:53: warning: comparison of integer expressions of different signedness: 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   93 |   while (pickedLow[i].size() + pickedHigh[i].size() < k) {
      |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
tickets.cpp:105:21: warning: comparison of integer expressions of different signedness: 'int' and 'const long unsigned int' [-Wsign-compare]
  105 |   for (int j = 1; j <= min(pickedLow[i].size(), high[i].size()); j++) {
      |                   ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
tickets.cpp:118:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  118 |    for (int k = 0; k < b[i].size(); k++) {
      |                    ~~^~~~~~~~~~~~~
tickets.cpp:68:7: warning: variable 'binary' set but not used [-Wunused-but-set-variable]
   68 |  bool binary = true;
      |       ^~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...