제출 #1274318

#제출 시각아이디문제언어결과실행 시간메모리
1274318mdobricBoarding Passes (BOI22_passes)C++20
100 / 100
155 ms37400 KiB
#include <bits/stdc++.h>
using namespace std;

const int maxn = 100005, maxg = 15;
int n, g;
string s;
double prosli[maxn][maxg], dp[1 << maxg];
int red[maxg], red2[maxg];
double ukp[maxg], calcb[maxg][maxg][maxn], calcf[maxg][maxg][maxn];
vector <int> mjesta[maxg];
double ans = 1e18;

int binary_search (int x, int mask){
	int low = 0, high = ukp[red[x]], mid, mid2;
	while (low < high){
		//cout << low << "      " << high << endl;
		mid = (low + high) / 2;
		mid2 = mid + 1;
		double suma = 0, suma2 = 0;
		double m = mid, m2 = mid2;
		suma += m * (m - 1) / 2;
		suma += (ukp[red[x]] - m) * (ukp[red[x]] - m - 1) / 2;
		suma = suma / 2;
		suma2 += mid2 * (m2 - 1) / 2;
		suma2 += (ukp[red[x]] - m2) * (ukp[red[x]] - m2 - 1) / 2;
		suma2 = suma2 / 2;
		for (int j = 0; j < g; j++){
			if (mask & (1 << j) and j != x){
				suma += calcf[x][j][mid];
				suma += calcb[x][j][mjesta[red[x]].size() - mid];
				suma2 += calcf[x][j][mid2];
				suma2 += calcb[x][j][mjesta[red[x]].size() - mid2];
			}
		}
		
		if (suma < suma2) high = mid;
		else low = mid2;
	}
	return low;
}

double rek (int mask){
	if (abs(dp[mask] + 1) > 0.1) return dp[mask];
	dp[mask] = 1e18;
	for (int i = 0; i < g; i++){
		if (mask & (1 << i)){
			double tr = rek(mask - (1 << i));
			int k = binary_search(i, mask - (1 << i));
			double kk = k;
			double suma = 0;
			suma += kk * (kk - 1) / 2;
			suma += (ukp[red[i]] - kk) * (ukp[red[i]] - kk - 1) / 2;
			suma = suma / 2;
			//cout << tr << " " << suma << endl;
			for (int j = 0; j < g; j++){
				if (mask & (1 << j) and j != i){
					suma += calcf[i][j][k];
					suma += calcb[i][j][mjesta[red[i]].size() - k];
				}
			}
			tr += suma;
			//cout << i << " " << mask << "    " << k << "  " << suma << "  " << tr << endl;
			dp[mask] = min(dp[mask], tr);
		}
	}
	//cout << mask << " " << dp[mask] << endl;
	return dp[mask];
}

int main (void){
	
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	cin >> s;
	n = s.size();
	memset(prosli, 0, sizeof prosli);
	for (int i = 0; i < n; i++){
		if (i != 0){
			for (int j = 0; j < 15; j++) prosli[i][j] = prosli[i - 1][j];
		}
		int j = s[i] - 'A';
		if (prosli[i][j] == 0) red[g] = j, red2[j] = g, g++;
		prosli[i][j]++;
		ukp[j]++;
		mjesta[j].push_back(i);
	}
	for (int mask = 0; mask < (1 << g); mask++) dp[mask] = -1;
	dp[0] = 0;
	for (int g1 = 0; g1 < g; g1++){
		for (int g2 = 0; g2 < g; g2++){
			if (g1 != g2){
				for (int i = 0; i < mjesta[red[g1]].size(); i++){
					int pos = mjesta[red[g1]][i];
					calcf[g1][g2][i + 1] = calcf[g1][g2][i] + prosli[pos][red[g2]];
					
				}
				for (int i = mjesta[red[g1]].size() - 1; i >= 0; i--){
					int pos = mjesta[red[g1]][i];
					calcb[g1][g2][mjesta[red[g1]].size() - i] = calcb[g1][g2][mjesta[red[g1]].size() - i - 1] + ukp[red[g2]] - prosli[pos][red[g2]];
					//cout << g1 << " " << g2 << " " << mjesta[red[g1]].size() - i << " " <<calcb[g1][g2][mjesta[red[g1]].size() - i] << endl;
				}
				
			}
		}
	}
	//rek(16);
	ans = rek((1 << g) - 1);	
	cout << fixed << setprecision(10);
	cout << ans << "\n";	

	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...