AtCoder Beginner Contest 224
A - Tires
思路分析:
代碼如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
string s;
cin >> s;
string temp;
if (s[s.size() - 1] == 'r')
{
cout << "er" << endl;
}
else
{
cout << "ist" << endl;
}
return 0;
}
B - Mongeness
思路分析:
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 60;
int a[maxn][maxn];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int h, w;
cin >> h >> w;
for (int i = 1; i <= h; i++)
{
for (int j = 1; j <= w; j++)
{
cin >> a[i][j];
}
}
bool flag = 0;
for (int i = 1; i < h; i++)
{ //i1
for (int j = i + 1; j <= h; j++)
{ //i2
for (int k = 1; k < w; k++)
{ //j1
for (int x = k + 1; x <= w; x++)
{ //j2
int x1 = a[i][k] + a[j][x];
int x2 = a[j][k] + a[i][x];
if (x1 > x2)
{
flag = 1;
break;
}
else
continue;
}
if (flag)
break;
}
if (flag)
break;
}
if (flag)
break;
}
if (flag)
{
cout << "No" << endl;
}
else
cout << "Yes" << endl;
return 0;
}
C - Triangle?
思路分析:
- 在坐標系隨便取三個點,如果這三個點不在同一條直線上,那么必然組成一個三角形,所以只需要判斷哪三個點在同一條直線上減去即可,然后數據范圍決定可以暴力。
- 注意如何判斷是否在同一條直線,我用的是斜率但是要改成乘法(因為會有0)。
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500;
int x[maxn], y[maxn];
const double eps = 1e-6;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> x[i] >> y[i];
}
long long ans = n * (n - 1) * (n - 2) / (3 * 2);
for (int i = 1; i < n - 1; i++)
{
//1
for (int j = i + 1; j < n; j++)
{
//2
for (int k = j + 1; k <= n; k++)
{
//3
int x1 = x[i], y1 = y[i];
int x2 = x[j], y2 = y[j];
int x3 = x[k], y3 = y[k];
if (x3 * y2 - x1 * y2 - x3 * y1 == x2 * y3 - x2 * y1 - x1 * y3)
ans--;
}
}
}
cout << ans << endl;
return 0;
}
D - 8 Puzzle on Graph
思路分析:
- 比賽的時候看這題題目一直沒看懂,最后十多分鍾看懂了(要隊友給我說了一遍題意)但是當時沒有想法,最后十分鍾發現數據范圍可以暴力,但是沒來得及寫。
- 題目的意思就是先給出一個無向圖,然后有八個塊,每個塊的序號和他所在的頂點序號不同,最后要你通過把塊轉移操作(塊可以轉移到沒有塊的頂點上),最后要使得每個塊的序號和頂點序號一樣,求需要多少次塊轉移操作,如果不能轉移到要求的結果,輸出-1。
- 首先我們要轉換一下,轉換成第\(i\)個頂點在第\(j\)塊,並且用塊\(9\)表示為空,比如第一個樣例我們轉換后就是931456782。然后我們要使得它變成123456789,我們就可以使用BFS來解決這題,我們把當前為空塊頂點相連的邊的塊全部都轉移一次,然后存到隊列里,用隊列解決問題,用map來儲存答案。
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 50;
vector<int> e[maxn];
map<string, int> mp;
int main()
{
string s = "999999999";
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int m;
cin >> m;
for (int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
for (int i = 1; i <= 8; i++)
{
int x;
cin >> x;
s[x - 1] = i + '0';
}
mp[s] = 0;
queue<string> q;
q.push(s);
while (!q.empty())
{
string s = q.front();
q.pop();
int u = 0;
for (int i = 1; i <= 9; i++)
{
if (s[i - 1] == '9')
{
u = i;
}
}
for (auto x : e[u])
{
string t = s;
swap(t[u - 1], t[x - 1]);
//每一個相鄰的邊都操作一次
if (mp.count(t))
continue;
//出現過了
mp[t] = mp[s] + 1;
q.push(t);
}
}
if (mp.count("123456789") == 0)
{
cout << -1 << endl;
}
else
{
cout << mp["123456789"] << endl;
}
return 0;
}
E - Integers on Grid
思路分析:
- 這題看題解的,但是題解很長還是英文,有點難看懂。
- 我直接講做法吧,我們先把值對應到一個向量中,這樣的話其實值在map里面已經排好序了,然后反向遍歷map,這樣可以使得我們當前拿到的是一個最大值,因為只有這樣我們能保證正確性,因為只有比所選數小才能通過移動到達這個值,然后對於最大值他的答案肯定是\(0\),然后對於和他同一行同一列的元素來說,答案一個就是得到的值加1和之前算出來的答案比較得到的最大值。
- 狀態轉移其實就是\(dp[i] = max(當前行的最大值,當前列的最大值)\)。
- \(當前行的最大值 = max(dp[i] + 1,之前算出的最大值)\)。
- \(當前列的最大值 = max(dp[i] + 1,之前算出的最大值)\)。
代碼如下:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
map<int, vector<int>> mp;
int r[maxn];
int c[maxn];
int val[maxn];
int dp[maxn];
int rmax[maxn];
int cmax[maxn];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int h, w, n;
cin >> h >> w >> n;
for (int i = 1; i <= n; i++)
{
cin >> r[i] >> c[i] >> val[i];
mp[val[i]].push_back(i);
}
for (auto it = mp.rbegin(); it != mp.rend(); it++)
{
for (auto i : it->second)
{
dp[i] = max(rmax[r[i]], cmax[c[i]]);
}
for (auto i : it->second)
{
rmax[r[i]] = max(rmax[r[i]], dp[i] + 1);
cmax[c[i]] = max(cmax[c[i]], dp[i] + 1);
}
}
for (int i = 1; i <= n; i++)
{
cout << dp[i] << endl;
}
return 0;
}