🔵
【ABC345】AtCoder Beginner Contest 345【C++】
コンテスト名
モノグサプログラミングコンテスト2024(AtCoder Beginner Contest 345)
コンテストURL
開催日
2024/03/16 21:00-22:40
A: Leftrightarrow
解法
- 条件を満たすかそれぞれ確かめる
- 1 文字目は
<
-
S.size()
文字目は>
- ほかはすべて
=
- 1 文字目は
ABC345A.cpp
#include <iostream>
#include <string>
using namespace std;
int main(){
string s;
cin >> s;
if(s[0]!='<'){
cout << "No" << endl;
return 0;
}
if(s.back()!='>'){
cout << "No" << endl;
return 0;
}
for(int i=1; i<s.size()-1; i++){
if(s[i]!='='){
cout << "No" << endl;
return 0;
}
}
cout << "Yes" << endl;
return 0;
}
B: Integer Division Returns
解法
-
のときa \geqq 0, b > 0 \left\lceil\frac{a}{b}\right\rceil = \left\lfloor\frac{a + b - 1}{b}\right\rfloor - C++ の整数除算は正でも負でも小数点以下を切り捨てる
-
が負のときはそのまま出力X
ABC345B.cpp
#include <iostream>
using namespace std;
int main(){
long long int x;
cin >> x;
if(x>=0){
cout << (x + (10-1))/10 << endl;
}else{
cout << x/10 << endl;
}
return 0;
}
C: One Time Swap
解法
- 文字列
においてS 文字目とi 文字目が異なる整数の組j の個数を求める(i, j) -
を満たす整数の組1 \leqq i < j \leqq N は(i, j) 通り{}_N \mathrm{C}_2 -
文字目とi 文字目が同じときは入れ替えても元の文字列j と変わらないS - 文字
x
が文字列 にS 個含まれているとき2 \leqq k \leqq N x
同士を入れ替えてできる元の文字列 と変わらない文字列はS 通り{}_k \mathrm{C}_2 - 各文字の個数を
unordered_map<char, long long int>
で管理して元の文字列 と変わらない場合を引くS - 「元の文字列
と変わらない場合」も 1 通りと数えるためS +1
する
ABC345C.cpp
#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
int main(){
string s;
cin >> s;
unordered_map<char, long long int> M;
bool same = false;
long long int n = s.size();
for(int i=0; i<n; i++){
M[s[i]]++;
if(M[s[i]]>1){
same = true;
}
}
long long int sum = (n*(n-1))/2;
long long int cnt = 0;
for(unordered_map<char, long long int>::iterator it=M.begin(); it!=M.end(); it++){
pair<char, long long int> item = *it;
if((item.second*(item.second-1))/2){
cnt += (item.second*(item.second-1))/2;
}
}
if(same){
cout << sum - cnt + 1 << endl;
}else{
cout << sum << endl;
}
return 0;
}
D: Tiling
解法
- 全探索
- 順列全探索 + bit 全探索 + マス目全探索
- 深さ優先探索 (DFS)
- 左上からタイルを敷き詰めて全マス埋まれば
Yes
- 標準エラー出力
cerr << endl
でどのように埋まったか確認できる
- 順列全探索 + bit 全探索 + マス目全探索
- タイルを並べる順番を順列全探索
- タイルの向きを bit 全探索
- 「使用されないタイル」は順列の後ろのほうにあると考える
- 順列の最後のタイルまで使用する場合(
枚すべて利用する場合)の判定場所に注意N - 空いているマスの座標を代入する変数を
-1
などで初期化しておくと判定が楽
- 深さ優先探索 (DFS)
-
vector<int>
で使用したタイルを記録する -
for
とswap
で向きを探索
-
ABC345D_1.cpp
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
int n, h, w;
cin >> n >> h >> w;
vector<int> A(n), B(n);
for(int i=0; i<n; i++){
cin >> A[i] >> B[i];
}
vector<int> P(n);
for(int i=0; i<n; i++){
P[i] = i;
}
do{
for(int i=0; i<(1<<n); i++){
vector<vector<int>> M(h, vector<int>(w));
for(int j=0; j<n; j++){
int check = (i & (1<<j));
int a, b;
if(check){
a = A[P[j]];
b = B[P[j]];
}else{
a = B[P[j]];
b = A[P[j]];
}
int nh = -1, nw = -1;
for(int k=0; k<h; k++){
for(int l=0; l<w; l++){
if(!M[k][l] && nh==-1){
nh = k;
nw = l;
}
}
}
if(nh+a>h || nw+b>w){
break;
}
bool flag = true;
for(int k=0; k<a; k++){
for(int l=0; l<b; l++){
if(M[nh+k][nw+l]){
flag = false;
}
M[nh+k][nw+l] = P[j] + 1;
}
}
if(!flag){
break;
}
flag = true;
for(int k=0; k<h; k++){
for(int l=0; l<w; l++){
if(!M[k][l]){
flag = false;
}
}
}
if(flag){
cout << "Yes" << endl;
for(int k=0; k<h; k++){
for(int l=0; l<w; l++){
cerr << M[k][l];
}
cerr << endl;
}
return 0;
}
}
}
}while(next_permutation(P.begin(), P.end()));
cout << "No" << endl;
return 0;
}
ABC345D_2.cpp
#include <iostream>
#include <vector>
using namespace std;
int n, h, w;
vector<int> A, B;
bool dfs(vector<vector<int>> &M, vector<int> &used){
int ni = -1, nj = -1;
for(int i=0; i<h; i++){
for(int j=0; j<w; j++){
if(!M[i][j] && ni==-1){
ni = i;
nj = j;
}
}
}
if(ni==-1){
for(int k=0; k<h; k++){
for(int l=0; l<w; l++){
cerr << M[k][l];
}
cerr << endl;
}
return true;
}
for(int i=0; i<n; i++){
if(used[i]){
continue;
}
int a = A[i], b = B[i];
for(int j=0; j<2; j++){
swap(a, b);
if(ni+a>h || nj+b>w){
continue;
}
bool flag = true;
vector<vector<int>> Ms = M;
vector<int> useds = used;
for(int k=0; k<a; k++){
for(int l=0; l<b; l++){
if(Ms[ni+k][nj+l]){
flag = false;
}
Ms[ni+k][nj+l] = i + 1;
}
}
if(!flag){
continue;
}
useds[i] = 1;
if(dfs(Ms, useds)){
return true;
}
}
}
return false;
}
int main(){
cin >> n >> h >> w;
A.resize(n);
B.resize(n);
for(int i=0; i<n; i++){
cin >> A[i] >> B[i];
}
vector<vector<int>> M(h, vector<int>(w, 0));
vector<int> used(n, 0);
if(dfs(M, used)){
cout << "Yes" << endl;
}else{
cout << "No" << endl;
}
return 0;
}
Discussion