constint maxn=20000+10; constint maxm = 15; int n, m; string str, word[maxn][maxm]; map<pair<string,string>, int> ha;
intmain(){ freopen("database.in", "r", stdin); freopen("database.out", "w", stdout); scanf("%d%d\n", &n, &m); for (int i = 1; i <= n; i ++) { getline(cin, str); str = str + ","; int len = str.length(); int c = 0; int last = 0; for (int j = 0; j < len; j ++) if (str[j] == ',') { c ++; word[i][c] = str.substr(last, j - last); last = j + 1; // printf("(%d,%d)=", i,c); // cout << word[i][c] << endl; } } for (int c = 1; c <= m; c ++) for (int d = c + 1; d <= m; d ++) { ha.clear(); for (int i = 1; i <= n; i ++) { pair<string, string> cur = make_pair(word[i][c], word[i][d]); if (ha.count(cur)) { printf("NO\n"); printf("%d %d\n", ha[cur], i); printf("%d %d\n", c, d); return0; } ha[cur] = i; } } printf("YES\n"); return0; }
F. Funny Language
题意:定义一个字符串能生成的字符串为,选择其中若干个字符重新排列得到的字符串。给定 m 个字符串,构造 n 个字符串,使得这 n 个字符串不能与 m 个给定的重复,且可以被这 m 个字符串中尽量多的生成。
一个显然的结论是,若选了某个字符串,其中的每个子串被生成的次数都不会少于这个原串,所以可以先选一个字符的串,然后在逐步加字符,一步一步考虑。可以使用类似 Dijkstra 的做法来一步步扩展,每次选当前被生成次数最多的字符串拓展,直到确定完 n 个合法的字符串。
voidadd(string x) { for (int i = 0; i < 26; i++) d[i] = 0; for (int i = 0; i < x.length(); i++) d[x[i]-'A']++;
int tot = 0; for (int i = 0; i < M; i++) { bool bad = false; for (int j = 0; j < 26; j++) { if (distro[i][j] < d[j]) { bad = true; break; } } if (!bad) tot++; }
pq.push (make_pair (tot, x)); }
intmain() { fin >> N >> M; for (int i = 0; i < M; i++) { fin >> s[i];
int K, N, M; int dp[MAXN][MAXN][MAXM]; // [i] questions correct out of [j], [k]-th prob, smallest max int prev[MAXN][MAXN][MAXM]; vector <pair <int, int> > pposs[MAXM];
int res; pair <int, int> answer[MAXM];
intgetp(int num, int den) { int t = (100 * num + den / 2) / den; if (2 * t * den == 200 * num + den && t % 2 == 1) --t; return t; }
intsolve(int lo) { for (int i = 0; i < MAXN; i++) for (int j = 0; j < MAXN; j++) for (int k = 0; k < MAXM; k++) dp[i][j][k] = 1000;
dp[0][0][0] = 0; for (int i = 0; i < M; i++) { for (int j = 0; j <= K; j++) for (int k = 0; k <= N; k++) { for (int l = 0; l < pposs[i].size(); l++) { if (pposs[i][l].second < lo) continue; int x = pposs[i][l].first, y = pposs[i][l].second;
if (j + x > K || k + y > N) break;
if (dp[j+x][k+y][i+1] > max (y, dp[j][k][i])) { dp[j+x][k+y][i+1] = max (y, dp[j][k][i]); prev[j+x][k+y][i+1] = l; } } } }
//cout << lo << " " << dp[K][N][M] << "\n"; if (dp[K][N][M] < 1000) return dp[K][N][M] - lo; return-1; }
intmain() { fin >> K >> N >> M; for (int i = 0; i < M; i++) { pposs[i].clear(); int x; fin >> x;
for (int j = 1; j <= 100; j++) for (int k = 0; k <= j; k++) { if (getp (k, j) == x) { //cout << i << " " << k << " " << j << "\n"; pposs[i].push_back (make_pair (k, j)); } } }
res = 100; for (int i = N / M; i >= 1; i--) { int t = solve (i); if (t < res && t != -1) { res = t;
int ck = K, cn = N, cm = M; while (cm) { --cm; int x = pposs[cm][prev[ck][cn][cm+1]].first; int y = pposs[cm][prev[ck][cn][cm+1]].second; answer[cm] = make_pair (x, y); ck -= x; cn -= y; } } }
for (int i = 0; i < M; i++) fout << answer[i].second - answer[i].first << " " << answer[i].second << "\n"; return0; }