Cod sursa(job #3302661)

Utilizator Ilie_MityIlie Dumitru Ilie_Mity Data 9 iulie 2025 20:44:14
Problema Barman Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.14 kb
// Ilie "The-Winner" Dumitru
// Dumnezeu sa o ierte
#include<bits/stdc++.h>
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using ll=long long;
constexpr int NMAX=605;
constexpr ll MOD=1000000007;

ll MinAssignment(const std::vector<std::vector<ll> >& W) {
	int n=sz(W), m=sz(W[0]);             // assert(n <= m);
	std::vector<ll> v(m), dist(m);       // v: potential
	std::vector<int> L(n, -1), R(m, -1); // matching pairs
	std::vector<int> idx(m), prev(m); std::iota(all(idx), 0);
	ll w=0, h=0; int j, l, s=0, t=0; auto reduce=[&]() { if(s==t) {
			l=s; w=dist[idx[t++]]; for(int k=t;k<m;++k) { j=idx[k];
				h=dist[j]; if(h>w) { continue; } if(h<w) t=s, w=h;
				idx[k]=idx[t]; idx[t++]=j; } for(int k=s;k<t;++k) {
				j=idx[k]; if(R[j]<0) return 1; } }
		int q=idx[s++], p=R[q], k; for(k=t;k<m;++k) { j=idx[k];
			h=W[p][j]-W[p][q]+v[q]-v[j]+w; if(h<dist[j]) {
				dist[j]=h; prev[j]=p; if(h==w) { if(R[j]<0) return 1;
					idx[k]=idx[t]; idx[t++]=j; } } } return 0; };
	for(int i=0;i<n;++i) { for(int k=0;k<m;++k)
			dist[k]=W[i][k]-v[k], prev[k]=i;
		s=t=0; while(!reduce());
		for(int k=0;k<l;++k) v[idx[k]]+=dist[idx[k]]-w;
		for(int k=-1;k!=i;) R[j]=k=prev[j], std::swap(j, L[k]); }
	ll ret=0; for(int i=0;i<n;++i) ret+=W[i][L[i]];
	return ret; } // (i, L[i]) is a solution


std::pair<int, std::vector<int> > hungarian(const std::vector<std::vector<int> > &a) {
#define rep(i, j, k) for(int i=j;i<k;++i)
	if (a.empty()) return {0, {}};
	int n = sz(a) + 1, m = sz(a[0]) + 1;
	std::vector<int> u(n), v(m), p(m), ans(n - 1);
	rep(i,1,n) {
		p[0] = i;
		int j0 = 0; // add "dummy" worker 0
		std::vector<int> dist(m, INT_MAX), pre(m, -1);
		std::vector<bool> done(m + 1);
		do { // dijkstra
			done[j0] = true;
			int i0 = p[j0], j1, delta = INT_MAX;
			rep(j,1,m) if (!done[j]) {
				auto cur = a[i0 - 1][j - 1] - u[i0] - v[j];
				if (cur < dist[j]) dist[j] = cur, pre[j] = j0;
				if (dist[j] < delta) delta = dist[j], j1 = j;
			}
			rep(j,0,m) {
				if (done[j]) u[p[j]] += delta, v[j] -= delta;
				else dist[j] -= delta;
			}
			j0 = j1;
		} while (p[j0]);
		while (j0) { // update alternating path
			int j1 = pre[j0];
			p[j0] = p[j1], j0 = j1;
		}
	}
	rep(j,1,m) if (p[j]) ans[p[j] - 1] = j - 1;
	return {-v[0], ans}; // min cost
#undef rep
}




int oo=1LL<<25;
std::vector<std::vector<int> > W;
int N;
int v[NMAX], aux[NMAX];
std::map<int, std::vector<int> > poss;

int main()
{
	FILE* f=fopen("barman.in", "r"), *g=fopen("barman.out", "w");
	int i, j;
	ll ans=oo;

	fscanf(f, "%d", &N);
	W.resize(N);
	for(i=0;i<N;++i)
	{
		fscanf(f, "%d", v+i);
		aux[i]=v[i];
		W[i].resize(N);
	}

	std::sort(aux, aux+N);
	for(i=0;i<N;++i)
		poss[aux[i]].push_back(i);

	for(i=0;i<N;++i)
	{
		for(j=0;j<N;++j)
		{
			std::fill(all(W[j]), oo);
			for(int p : poss[v[j]])
			{
				p=(p+i)%N;
				if(j==p)
					W[j][p]=0;
				else
					W[j][p]=std::abs(p-j)+20;
				// else if(j<p)
					// W[j][p]=20+std::min(p-j, N+j-p);
				// else
					// W[j][p]=20+std::min(j-p, N+p-j);
			}
		}

		ll aux=hungarian(W).first;
		// for(j=0;j<N;++j)
			// printf("%d ", v[j]);
		// printf("-> %lld\n", aux);
		ans=std::min(ans, aux);
	}

	fprintf(g, "%lld\n", ans);

	fclose(f);
	fclose(g);
	return 0;
}