文章目录
ACM-ICPC North America Qualifier Contest 2018
A. Bingo Ties
题意: 有一个新bing游戏,给定n个 5 ∗ 5 5*5 5∗5的网格,每次玩家给定一组数列,如果这组数列包含了某2个网格某2行的所有数字,那么就会bingo。要求打印使得产生bingo的字典序最小的2个网格的序号。
题解: 通过分析可以知道,能够产生bingo的2行至少要有一个数字相同,因此如果2行数字存在至少一个数字相同,那么这2行对应的网格可能产生bingo。但是,可能出现一种情况使得在2行数字正在匹配的过程中,出现第3个网格的某一行先和2行数字的其中一行匹配上的情况,需要特判下。特判的方式如下:2行数字还没有bingo时会存在t的数字,那么如果第3个网格的某一行被完全包含于这t个数字的话,就会提前bingo。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2e5 + 10;
typedef long long LL;
typedef pair<int, int> PII;
int n, m, T;
struct Mat {
int g[110][100];
}gra[110];
int pos1, pos2;
bool judge2(int x, int l1, int p1, int y, int r1, int p2, int t) {
set<int> s;
for (int i = 1; i <= 5; ++i) {
if (gra[x].g[l1][i] != t) s.insert(gra[x].g[l1][i]);
if (gra[y].g[r1][i] != t) s.insert(gra[y].g[r1][i]);
}
if (s.size() < 5) return false;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= 5; ++j) {
int cnt = 0;
for (int k = 1; k <= 5; ++k)
if (s.count(gra[i].g[j][k])) cnt++;
if (cnt == 5) return true;
}
return false;
}
bool judge(int x, int line1, int y, int line2) {
for (int i = 1; i <= 5; ++i)
for (int j = 1; j <= 5; ++j)
if (gra[x].g[line1][i] == gra[y].g[line2][j]) {
int pos1 = i, pos2 = j;
if (!judge2(x, line1, pos1, y, line2, pos2, gra[x].g[line1][pos1])) return true;
}
return false;
}
int main() {
// freopen("in.txt", "r", stdin);
cin >> n;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= 5; ++j) {
for (int k = 1; k <= 5; ++k)
cin >> gra[i].g[j][k];
}
int flg = 0;
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
for (int l1 = 1; l1 <= 5; ++l1)
for (int r1 = 1; r1 <= 5; ++r1)
if (judge(i, l1, j, r1)) {
flg = 1;
cout << i << " " << j << endl;
return 0;
}
if (!flg) cout << "no ties";
return 0;
}
B. Das Blinkenlights
**题意: ** 签到
题解: 签到
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2e5 + 10;
typedef long long LL;
typedef pair<int, int> PII;
int n, m, T;
int gcd(int a, int b) {
return b == 0? a: gcd(b, a % b);
}
int lcm(int x, int y) {
return x * y / gcd(x, y);
}
int main() {
// freopen("in.txt", "r", stdin);
cin >> n >> m >> T;
if (T - lcm(n, m) >= 0) cout <<"yes";
else cout << "no";
return 0;
}
G. Left and Right
题意: 给定一个数字n,给定一个长度为n-1的字符串,要求构造一个数字序列,使得这个数字序列遇到R时递增,遇到L时递减。
题解: 本题是构造题,当前打印的数字与后面的L和R的数目有关系。由于要求字典序最小,L为递减,那么就需要让L前面的R先增到一个最小值,然后再用L去递减。所以,每次遇到R时,就去计算后面有几个L,如果后面有k个L,那么从当前可以使用的第k+1大的数字开始递减打印。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2e5 + 10;
typedef long long LL;
typedef pair<int, int> PII;
int n, m, T;
int main() {
// freopen("in.txt", "r", stdin);
cin >> n;
getchar();
int maxv = 1, minv = 1;
for (int i = 1; i < n; ++i) {
char op = getchar();
if (op == 'R') {
for (int j = maxv; j >= minv; --j) cout << j << endl;
maxv ++;
minv = maxv;
}
else maxv ++;
}
for (int i = maxv; i >= minv; --i) cout << i << endl;
return 0;
}
K. Run-Length Encoding, Run!
题意: 签到
题解: 签到
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 2e5 + 10;
typedef long long LL;
typedef pair<int, int> PII;
int n, m, T;
int main() {
// freopen("in.txt", "r", stdin);
string op, s;
cin >> op >> s;
if (op == "E") {
for (int j = 0, i = 0; i < s.size(); ) {
while(j < s.size() && s[i] == s[j]) j++;
cout << s[i] << j - i;
i = j;
}
}
else {
for (int i = 0; i < s.size(); ++i) {
if (!isdigit(s[i])) {
for (int j = 0; j < s[i + 1] - '0'; ++j) cout << s[i];
i++;
}
}
}
return 0;
}
// H3e2l3o1W1o3r4l2d1!2
// H3e2l3o1W1o3r4l2d1!2
// HHHeellloWooorrrrlld!!
// HHHeellloWooorrrrlld!!
L. Superdoku
题意: 给定n和m,给定m行,要求构造出其余n-m行,使得每行、每列都是1~n的全排列。 1 < = n < = 100 , 0 < = m < = n 1<=n<=100, 0<=m<=n 1<=n<=100,0<=m<=n
题解: 前m行给定,那么就是已知了一些约束关系,使用 h [ x ] [ i ] h[x][i] h[x][i]表示x曾经出现在第i行, l [ x ] [ i ] l[x][i] l[x][i]表示x曾经出现在第j列。那么对于第k行,就是在做二分图匹配,左部图为数字 1 ∼ n 1\sim n 1∼n,右部图为列 1 ∼ n 1\sim n 1∼n。如果当前数字x曾经出现在第t列,即 l [ x ] [ t ] = 1 l[x][t]=1 l[x][t]=1,那么左部图的x到右部图的t就没有连边。如果在做二分图匹配的过程中没有找到匹配,那么无解。
代码:
#include <bits/stdc++.h>
using namespace std;
int const N = 100 + 10;
typedef long long LL;
typedef pair<int, int> PII;
int n, m, T;
int g[N][N], h[N][N], l[N][N];
int match[N], st[N];
bool find(int x) {
for (int i = 1; i <= n; ++i) {
if (l[x][i]) continue;
if (!st[i]) {
st[i] = 1;
if (!match[i] || find(match[i])) {
match[i] = x;
return true;
}
}
}
return false;
}
int main() {
cin >> n >> m;
int flg = 1;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> g[i][j];
if (h[g[i][j]][i] || l[g[i][j]][j]) flg = 0;
h[g[i][j]][i] = 1, l[g[i][j]][j] = 1;
}
}
if (!flg) {
cout << "no\n";
return 0;
}
for (int i = m + 1; i <= n; ++i) {
memset(match, 0, sizeof match);
for (int j = 1; j <= n; ++j) {
memset(st, 0, sizeof st);
if (!find(j)) flg = 0;
}
for (int j = 1; j <= n; ++j) {
g[i][j] = match[j];
h[g[i][j]][i] = 1, l[g[i][j]][j] = 1;
}
}
if (!flg ) {
cout << "no\n";
return 0;
}
cout << "yes\n";
for (int i =1 ; i <=n ;++i) {
for (int j = 1; j <= n; ++j)
cout << g[i][j] << " ";
cout << endl;
}
return 0;
}