코드트리를 하는 김에 푸는 문제 중 재밌게 풀었거나 헷갈린 문제는 정리하고자 한다.
작성 코드
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
int main(void){
string s;
char c;
int t;
cin >> s >> c >> t;
tuple<string, char, int> tup = make_tuple(s, c, t);
cout << "secret code : " << get<0>(tup) << endl;
cout << "meeting point : " << get<1>(tup) << endl;
cout << "time : " << get<2>(tup) << endl;
return 0;
}
해설 코드 1 :Class
#include <iostream>
#include <string>
using namespace std;
class Spy {
public:
string secret_code;
char meeting_point;
int time;
Spy(string secret_code, char meeting_point, int time) {
this->secret_code = secret_code;
this->meeting_point = meeting_point;
this->time = time;
}
};
int main(){
string s_code;
char m_point;
int time;
cin >> s_code >> m_point >> time;
Spy s = Spy(s_code, m_point, time);
cout << "secret code : " << s.secret_code << endl;
cout << "meeting point : " << s.meeting_point << endl;
cout << "time : " << s.time << endl;
return 0;
}
해설 코드 2 :Tuple
#include <iostream>
#include <string>
#include <tuple>
using namespace std;
tuple<string, char, int> spy;
int main(){
string s_code;
char m_point;
int given_time;
cin >> s_code >> m_point >> given_time;
spy = make_tuple(s_code, m_point, given_time);
string secret_code;
char meeting_point;
int time;
tie(secret_code, meeting_point, time) = spy;
cout << "secret code : " << secret_code << endl;
cout << "meeting point : " << meeting_point << endl;
cout << "time : " << time << endl;
return 0;
}
첨언
- 문제 자체는 매우 쉬운 문제이다. / 정리한 이유 -> tuple, pair 개념을 처음 접했다.
- <tuple>을 include해서 사용, 아래와 같이 정의, 생성할 수 있다.
tuple<type, type, type> t = make_tuple(v1, v2, v3);
get<index>t; 이와 같이 값에 인덱스로 접근 할 수 있다.
tie(v4, v5, v6) = t; tie 함수를 사용해 내부 값을 한번에 전달할 수 있다.
- <utility>을 include해서 사용, 아래와 같이 정의, 생성할 수 있다.
pair형은 값이 무조건 쌍을 이룬다. - 2개
pair<type, type> p = make_pair(v1, v2);
p.first; p.second; 이와 같이 값에 접근 할 수 있다.
작성 코드
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Rain{
public:
string y, m, d;
string days;
Rain(){};
Rain(string y, string m, string d, string days) : y(y), m(m), d(d), days(days) {};
};
bool comp(const Rain& r1, const Rain& r2){
if (r1.y.compare(r2.y) < 0) return true;
else if (r1.y.compare(r2.y) == 0 && r1.m.compare(r2.m) < 0) return true;
else if (r1.y.compare(r2.y) == 0 && r1.m.compare(r2.m) == 0 && r1.d.compare(r2.d) < 0) return true;
return false;
}
int main() {
int n;
Rain r[100];
cin >> n;
for (int i = 0; i < n; i++){
string s1, s2, s3;
string year, month, day;
cin >> s1 >> s2 >> s3;
if (s3.compare("Rain")) {
i--;
n--;
continue;
}
year = s1.substr(0, 4);
month = s1.substr(5, 2);
day = s1.substr(8, 2);
r[i] = Rain(year, month, day, s2);
}
sort(r, r + n, comp);
cout << r[0].y << "-" << r[0].m << "-" << r[0].d << " " << r[0].days << " Rain";
return 0;
}
해설 코드
#include <iostream>
#include <string>
using namespace std;
class Forecast {
public:
string date, day, weather;
Forecast(string date, string day, string weather) {
this->date = date;
this->day = day;
this->weather = weather;
}
};
Forecast ans = Forecast("9999-99-99", "", "");
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
string date, day, weather;
cin >> date >> day >> weather;
Forecast f = Forecast(date, day, weather);
if(weather == "Rain")
if(ans.date >= f.date)
ans = f;
}
cout << ans.date << " " << ans.day << " " << ans.weather;
return 0;
}
첨언
- 굳이 날짜를 나눠서 비교해줄 필요없이 date 통째로 비교해도 된다는 생각에 미치지못했지만 덕분에 sort에서 비교함수를 쓰는 방법을 알았으니 럭키비키다.
sort(start, end, compare) 시작, 끝, 비교 함수를 인자로 가진다.
- 정렬 함수의 반환형은
bool 이며, 기왕이면 const type&로 인자를 받는다.
- a가 b보다 먼저 정렬되었으면하는 조건을
true 로 한다.
a > b 일 경우, 오름차순 / a < b 일 경우, 내림차순이다.
작성 코드
#include <iostream>
#include <tuple>
#include <string>
#include <algorithm>
using namespace std;
bool compare(const tuple<string, int, double>& t1, const tuple<string, int, double>& t2){
return get<1>(t1) > get<1>(t2);
}
int main() {
tuple<string, int, double> t[5];
string name;
int height;
double weight;
for (int i = 0; i < 5; i++){
cin >> name >> height >> weight;
t[i] = make_tuple(name, height, weight);
}
sort(t, t+5);
cout << "name" << endl;
for (int i = 0; i < 5; i++){
tie(name, height, weight) = t[i];
cout << name << " " << height << " ";
printf("%.1lf\n", weight);
}
sort(t, t+5, compare);
cout << endl;
cout << "height" << endl;
for (int i = 0; i < 5; i++){
tie(name, height, weight) = t[i];
cout << name << " " << height << " ";
printf("%.1lf\n", weight);
}
return 0;
}
해설 코드
#include <iostream>
#include <algorithm>
#include <string>
#define MAXN 5
using namespace std;
class Student{
public:
string name;
int height;
double weight;
Student(string name, int height, double weight) {
this->name = name;
this->height = height;
this->weight = weight;
}
Student(){}
};
bool Cmp1(Student a, Student b) {
return a.name < b.name;
}
bool Cmp2(Student a, Student b) {
return a.height > b.height;
}
Student students[MAXN];
int main(){
for (int i = 0; i < MAXN; i++){
string name;
int height;
double weight;
cin >> name >> height >> weight;
students[i] = Student(name, height, weight);
}
cout << fixed;
cout.precision(1);
sort(students, students + MAXN, Cmp1);
cout << "name" << endl;
for (int i = 0; i < MAXN; i++){
cout << students[i].name << " ";
cout << students[i].height << " ";
cout << students[i].weight << endl;
}
cout << endl;
sort(students, students + MAXN, Cmp2);
cout << "height" << endl;
for (int i = 0; i < MAXN; i++){
cout << students[i].name << " ";
cout << students[i].height << " ";
cout << students[i].weight << endl;
}
return 0;
}
첨언
-
복잡하지 않은 대부분의 경우(간단한 문제) tuple을 이용하는 것이 쉽다고 느껴진다.
-
90.0과 같은 값이 실수형 변수에 저장될 경우, 90으로 저장한다. -> 고려 안해 한번 틀림
printf("%.nlf", value); 로 푸는 것도 문제는 없어보이지만..
cout << fixed; cout.precision(n); 을 이용하는 것이 좋아보인다.
cout.precision(n); n자리수까지만 출력한다.
cout << fixed; precision(n)에서 지정하는 n이 소수점 아래 자리수가 된다.
#include <iostream>
using namespace std;
int main(void){
cout << fixed;
cout.precision(1);
int ai(1), bi(2), ci(3);
float af(1), bf(2), cf(3);
double ad(1.06), bd(2.06), cd(3.06);
cout << ai << " " << bi << " " << ci << endl;
cout << af << " " << bf << " " << cf << endl;
cout << ad << " " << bd << " " << cd << endl;
ad = 1.05; bd = 2.05; cd = 3.05;
cout << ad << " " << bd << " " << cd << endl;
return 0;
}
작성 코드
#include <iostream>
#include <cmath>
#include <algorithm>
#include <tuple>
using namespace std;
int main() {
int n, num(1), x, y, dis;
tuple<int, int>* t;
cin >> n;
t = new tuple<int, int>[n];
for (int i = 0; i < n; i++){
cin >> x >> y;
dis = abs(x - 0) + abs(y - 0);
t[i] = make_tuple(dis, num++);
}
sort(t, t+n);
for (int i = 0; i < n; i++){
tie(ignore, num) = t[i];
cout << num << endl;
}
delete[] t;
return 0;
}
해설 코드
#include <iostream>
#include <algorithm>
#include <cmath>
#include <utility>
#define MAXN 1000
using namespace std;
int GetDistFromOrigin(int x, int y) {
return abs(x) + abs(y);
}
pair<int, int> distances[MAXN];
int main(){
int n;
cin >> n;
int x, y;
for(int i = 0; i < n; i++) {
cin >> x >> y;
distances[i] = make_pair(GetDistFromOrigin(x, y), i + 1);
}
sort(distances, distances + n);
for(int i = 0; i < n; i++)
cout << distances[i].second << endl;
return 0;
}
첨언
- 저장할 값이 2개밖에 없는 경우에는
pair<type, type>을 이용해보자
물론 푸는데 상관은 없지만 알맞게 쓰면 기분이 좋다.
pair, tuple의 경우에는 객체 정렬시 앞에 있는 인자부터 순차적으로 따져 오름차순으로 정렬해준다.
인자값 1을 기준으로 오름차순 -> 만약 인자값 1이 같다면 인자값 2 기준으로 -> 만약 인자값 2도 같다면 인자값 3 기준으로 -> ...
작성 코드
#include <iostream>
#include <algorithm>
using namespace std;
class Array{
public:
int key;
int num;
Array(){};
Array(int key, int num) : key(key), num(num) {};
};
bool compare(const Array& arr1, const Array& arr2){
if (arr1.num == arr2.num) return arr1.key < arr2.key;
return arr1.num < arr2.num;
}
int main() {
int n, key(0), num;
Array* array;
cin >> n;
array = new Array[n];
for (int i = 0; i < n; i++){
cin >> num;
array[i] = Array(key++, num);
}
sort(array, array + n, compare);
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
if (array[j].key == i) {
cout << j + 1 << " ";
break;
}
}
}
delete[] array;
return 0;
}
해설 코드 :Class
#include <iostream>
#include <algorithm>
#define MAX_NUM 1000
using namespace std;
class Number{
public:
int number;
int index;
Number(int number, int index) {
this->number = number;
this->index = index;
}
Number(){}
};
bool Cmp(Number a, Number b) {
if(a.number != b.number)
return a.number < b.number;
return a.index < b.index;
}
Number numbers[MAX_NUM];
int main() {
int n, num_cache;
int answer[MAX_NUM];
cin >> n;
for(int i = 0; i < n; i++) {
cin >> num_cache;
numbers[i] = Number(num_cache, i);
}
sort(numbers, numbers + n, Cmp);
for(int i = 0; i < n; i++)
answer[numbers[i].index] = i + 1;
for(int i = 0; i < n; i++){
cout << answer[i] << " ";
}
return 0;
}
해설 코드 :Pair
#include <iostream>
#include <vector>
#include <algorithm>
#define MAX_NUM 1000
using namespace std;
int main() {
int n, num_cache;
int answer[MAX_NUM];
vector<pair<int, int> > numbers;
cin >> n;
for(int i = 0; i < n; i++) {
cin >> num_cache;
numbers.push_back(make_pair(num_cache, i));
}
sort(numbers.begin(), numbers.end());
for(int i = 0; i < n; i++)
answer[numbers[i].second] = i + 1;
for(int i = 0; i < n; i++){
cout << answer[i] << " ";
}
return 0;
}
첨언
- 이중 for문을 만들지 않고 아래와 같이 int형 배열을 하나 만들어서 쉽게 해결할 수 있었다.
array[i].key는 입력받은 순서이고, array는 지금 정렬되었으니 간단히 원래 순서대로 정렬 후 변경 된 위치를 출력할 수 있다.
for (int i = 0; i < n; i++){
solve[array[i].key] = i + 1;
}
for (int i = 0; i < n; i++){
cout << solve[i] << " ";
}
- 구현됐으니, 원하는 답이 나왔으니 끝! 이 아니라 좀 더 나은 알고리즘이 있는지 생각해보는게 좋을 것 같다.
작성 코드
#include <iostream>
#include <utility>
#include <string>
using namespace std;
int Func(int m1, int m2, int d1, int d2, bool reverse){
int elapse_day(0);
int month_day[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
elapse_day = d2 - d1;
for (int i = m1; i < m2; i++){
elapse_day += month_day[i-1];
}
if (reverse) return 7 - (elapse_day % 7);
return elapse_day % 7;
}
int GuessDay(int m1, int m2, int d1, int d2){
pair<int, int> day1 = make_pair(m1, d1);
pair<int, int> day2 = make_pair(m2, d2);
if (day1 > day2) return Func(m2, m1, d2, d1, true);
else return Func(m1, m2, d1, d2, false);
}
int main() {
int m1, m2, d1, d2;
string day_of_week[7] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
cin >> m1 >> d1 >> m2 >> d2;
cout << day_of_week[GuessDay(m1, m2, d1, d2)];
return 0;
}
해설 코드
#include <iostream>
#include <string>
using namespace std;
int NumOfDays(int m, int d) {
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int total_days = 0;
for(int i = 1; i < m; i++)
total_days += days[i];
total_days += d;
return total_days;
}
int main() {
int m1, m2, d1, d2;
cin >> m1 >> d1 >> m2 >> d2;
int diff = NumOfDays(m2, d2) - NumOfDays(m1, d1);
while(diff < 0)
diff += 7;
string day_of_week[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
cout << day_of_week[diff % 7];
return 0;
}
첨언
- A부터 B까지 총 시간, 총 일수 등등을 구하는 식이 내 안에서 정립된 기분이다.
(작성 코드의 elapse_day 구하는 식)
- tuple, pair의 인수별 오름차순 비교는 너무 좋은 기능같다.
작성 코드
#include <iostream>
#include <string>
using namespace std;
int Func(int m1, int d1, int m2, int d2, int d_w_n){
int elapse_day(0);
int day_times(0);
int month_day[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
elapse_day = d2 - d1;
for (int i = m1; i < m2; i++) elapse_day += month_day[i-1];
day_times = elapse_day / 7;
if (elapse_day % 7 < d_w_n) return day_times;
else return day_times + 1;
}
int main() {
int m1, d1, m2, d2, day_week_num;
string day_week;
string day_weeks[7] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
cin >> m1 >> d1 >> m2 >> d2 >> day_week;
for (int i = 0; i < 7; i++){
if (!day_weeks[i].compare(day_week)){
day_week_num = i;
break;
}
}
cout << Func(m1, d1, m2, d2, day_week_num);
return 0;
}
해설 코드
#include <iostream>
using namespace std;
int NumOfDays(int m, int d) {
int days[13] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int total_days = 0;
for(int i = 1; i < m; i++)
total_days += days[i];
total_days += d;
return total_days;
}
int NumOfDay(string s) {
if(s == "Mon") return 0;
else if(s == "Tue") return 1;
else if(s == "Wed") return 2;
else if(s == "Thu") return 3;
else if(s == "Fri") return 4;
else if(s == "Sat") return 5;
return 6;
}
int ans;
int main() {
int m1, m2, d1, d2;
string A;
cin >> m1 >> d1 >> m2 >> d2;
cin >> A;
int start_date = NumOfDays(m1, d1);
int end_date = NumOfDays(m2, d2);
int cur_day = NumOfDay("Mon");
for(int date = start_date; date <= end_date; date++) {
if(cur_day == NumOfDay(A)) ans++;
cur_day = (cur_day + 1) % 7;
}
cout << ans;
return 0;
}
첨언
- 해설보다 맘에 드는 방식의 풀이를 한 것같아 기분이 좋음 (개인적 의견)
작성코드
#include <iostream>
#include <string>
using namespace std;
int BinToDec(string s){
int num(0);
for (int i = 0; i < s.length(); i++) num = num * 2 + (s[i] -'0');
return num;
}
void DecToBin(int d1, string& result){
int cnt(0), max_size(0);
int d;
for (d = d1; d >= 2; d/=2){
max_size++;
}
result.resize(max_size);
for (d = d1; d >= 2; d/=2){
result[cnt++] = d % 2 + '0';
}
result[cnt] = d + '0';
}
int main() {
string bin, result;
int dec;
cin >> bin;
dec = BinToDec(bin);
dec *= 17;
DecToBin(dec, result);
for (int i = result.length(); i>=0; i--) cout << result[i];
return 0;
}
해설코드
#include <iostream>
#include <algorithm>
#define MAX_DIGIT 20
using namespace std;
int main() {
string binary;
cin >> binary;
int num = 0;
for(int i = 0; i < (int) binary.size(); i++)
num = num * 2 + (binary[i] - '0');
num *= 17;
int digits[MAX_DIGIT] = {};
int cnt = 0;
while(true) {
if(num < 2) {
digits[cnt++] = num;
break;
}
digits[cnt++] = num % 2;
num /= 2;
}
for(int i = cnt - 1; i >= 0; i--)
cout << digits[i];
return 0;
}
첨언
- 이진수 1101이 주어졌을 때 이를 십진수로 바꾸는 방법은 아래와 같다.
for (int i = 0; i < 자리수; i++) num = num * 2 + bin[i]
이진수는 한자리가 늘어날때마다 2배가 되는 것을 이용(가중치)
- 십진수를 이진수로 바꾸는 법은
bin[cnt++] = dec % 2; dec /= 2;
이후 bin를 거꾸로 출력해주면 된다.
(코드에서는 bin[cnt] = dec를 해줬는데, 이유는 for 루프에서는 나머지를 못 넣었기때문)
- 어려운 문제는 아니었다, 구하는 방식도 다 알려줬고... 그런데 정리한 이유는 아래 코드 때문이다.
result.resize(max_size); -> result를 max_size로 만든다. (빈공간)
당연한 얘기지만 공간할당을 하지 않으면 cout << string을 할 수 없다.
특이한 점은 공간할당을 해주지 않아도 인덱스로 접근하여 출력은 할 수 있다. -> 주소접근이기에
작성 코드
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main() {
int n, x1, x2, offset(100);
int result[201] = {0,};
cin >> n;
for (int i = 0; i < n; i++){
cin >> x1 >> x2;
x1 += offset;
x2 += offset;
for (int k = x1; k < x2; k++) {
result[k]++;
}
}
sort(result, result + 201, greater<int>());
cout << result[0];
return 0;
}
해설 코드
#include <iostream>
#define MAX_N 100
#define MAX_R 200
#define OFFSET 100
using namespace std;
int n;
int x1[MAX_N], x2[MAX_N];
int checked[MAX_R + 1];
int main() {
cin >> n;
for(int i = 0; i < n; i++) {
cin >> x1[i] >> x2[i];
x1[i] += OFFSET;
x2[i] += OFFSET;
}
for(int i = 0; i < n; i++)
for(int j = x1[i]; j < x2[i]; j++)
checked[j]++;
int max = 0;
for(int i = 0; i <= MAX_R; i++)
if(checked[i] > max)
max = checked[i];
cout << max;
return 0;
}
첨언
- 겹치는 지점은 1차원 배열에
x1부터 x2까지 칠해주고
- 겹치는 구간은 1차원 배열에
x1부터 x2-1까지 칠해준다.
- 구간의 경우 x1, x1 + 1.. 과 같은 인덱스가 구간의 시작점으로 생각하는 것이다.
- 음수의 구간의 경우 오프셋을 정해서 양수 인덱스를 이용할 수 있도록 한다.
작성 코드
#include <iostream>
using namespace std;
class Area{
public:
int plus[1001] = {0,};
int minus[1001] = {0, };
int cur_pos = 0;
int cnt = 0;
Area(){};
void plusDir(int x){
int tmp = cur_pos + x;
for (cur_pos; cur_pos < tmp; cur_pos++){
if (cur_pos >= 0) {
plus[cur_pos]++;
}
else if (cur_pos < 0) {
minus[abs(cur_pos)]++;
}
}
}
void minusDir(int x){
int tmp = cur_pos - x;
for (cur_pos; cur_pos > tmp; cur_pos--){
if (cur_pos > 0) {
plus[cur_pos - 1]++;
}
else if (cur_pos < 0) {
minus[abs(cur_pos - 1)]++;
}
else {
minus[1]++;
}
}
}
void PrintAreaNumOver2(){
for (int i = 0; i < 1001; i++) {
if (plus[i] > 1) cnt++;
}
for (int i = 1; i < 1001; i++) {
if (minus[i] > 1) cnt++;
}
cout << cnt;
}
};
int main() {
int n, x;
char dir;
Area area;
cin >> n;
for (int i = 0; i < n; i++){
cin >> x >> dir;
if (dir == 'R'){
area.plusDir(x);
}
else {
area.minusDir(x);
}
}
area.PrintAreaNumOver2();
return 0;
}
해설 코드
#include <iostream>
#define MAX_N 100
#define MAX_R 2000
#define OFFSET 1000
using namespace std;
int n;
int x1[MAX_N], x2[MAX_N];
int checked[MAX_R + 1];
int main() {
cin >> n;
int cur = 0;
for(int i = 0; i < n; i++) {
int distance;
char direction;
cin >> distance >> direction;
if(direction == 'L') {
x1[i] = cur - distance;
x2[i] = cur;
cur -= distance;
}
else {
x1[i] = cur;
x2[i] = cur + distance;
cur += distance;
}
x1[i] += OFFSET;
x2[i] += OFFSET;
}
for(int i = 0; i < n; i++)
for(int j = x1[i]; j < x2[i]; j++)
checked[j]++;
int cnt = 0;
for(int i = 0; i <= MAX_R; i++)
if(checked[i] >= 2)
cnt++;
cout << cnt;
return 0;
}
작성 코드
#include <iostream>
#define BLACK 1
#define WHITE 2
#define OFFSET 100000
using namespace std;
class Tile{
public:
int black_count;
int white_count;
int last;
Tile() : black_count(0), white_count(0), last(0) {};
};
void BlackDir(Tile* area, int x, int& cur_pos){
for (int i = 0; i < x; i++){
if (!(area[cur_pos].black_count >= 2 && area[cur_pos].white_count >= 2)) {
area[cur_pos].black_count++;
area[cur_pos].last = BLACK;
}
cur_pos++;
}
cur_pos--;
}
void WhiteDir(Tile* area, int x, int& cur_pos){
for (int i = 0; i < x; i++){
if (!(area[cur_pos].black_count >= 2 && area[cur_pos].white_count >= 2)) {
area[cur_pos].white_count++;
area[cur_pos].last = WHITE;
}
cur_pos--;
}
cur_pos++;
}
void PrintNumberOfColor(Tile* area){
int black(0), white(0), grey(0);
for (int i = 0; i < 200001; i++){
if (area[i].black_count >= 2 && area[i].white_count >= 2) {
grey++;
continue;
}
if (area[i].last == WHITE) white++;
else if (area[i].last == BLACK) black++;
else continue;
}
cout << white << " " << black << " " << grey;
}
int main() {
Tile area [200001];
int n, x, cur_pos(OFFSET);
char dir;
cin >> n;
for (int i = 0; i < n; i++){
cin >> x >> dir;
if (dir == 'R') BlackDir(area, x, cur_pos);
else if (dir == 'L') WhiteDir(area, x, cur_pos);
}
PrintNumberOfColor(area);
return 0;
}
해설 코드
#include <iostream>
using namespace std;
#define MAX_K 100000
int n;
int a[2 * MAX_K + 1];
int cnt_b[2 * MAX_K + 1];
int cnt_w[2 * MAX_K + 1];
int b, w, g;
int main() {
cin >> n;
int cur = MAX_K;
for(int i = 1; i <= n; i++) {
int x;
char c;
cin >> x >> c;
if(c == 'L') {
while(x--) {
a[cur] = 1;
cnt_w[cur]++;
if(x) cur--;
}
}
else {
while(x--) {
a[cur] = 2;
cnt_b[cur]++;
if(x) cur++;
}
}
}
for(int i = 0; i <= 2 * MAX_K; i++) {
if(cnt_b[i] >= 2 && cnt_w[i] >= 2) g++;
else if(a[i] == 1) w++;
else if(a[i] == 2) b++;
}
cout << w << " " << b << " " << g;
return 0;
}
첨언
- 각 색의 바뀐 횟수, 최근에 바뀐 색을 멤버변수로 가지는 클래스를 만들어 해결하였다.
작성 코드
#include <iostream>
#include <algorithm>
#define OFFSET 1000
using namespace std;
int cord[2001][2001] = {{0,},};
void Area(int x1, int y1, int x2, int y2, int input){
for (int i = x1; i < x2; i++){
for (int j = y1; j < y2; j++){
cord[i][j] = input;
}
}
}
int main() {
int x1, y1, x2, y2;
int max_raw(-1), min_raw(2001);
int max_col(-1), min_col(2001);
int area(0);
bool already_covered = true;
for (int i = 1; i >= 0; i--){
cin >> x1 >> y1 >> x2 >> y2;
x1 += OFFSET;
y1 += OFFSET;
x2 += OFFSET;
y2 += OFFSET;
Area(x1, y1, x2, y2, i);
}
for (int i = 0; i < 2001; i++){
for (int j = 0; j < 2001; j++){
if (cord[i][j] == 1){
already_covered = false;
max_raw = max(max_raw, i);
min_raw = min(min_raw, i);
max_col = max(max_col, j);
min_col = min(min_col, j);
}
}
}
if (!already_covered)
area = (max_raw - min_raw + 1) * (max_col - min_col + 1);
cout << area;
return 0;
}
해설 코드
#include <iostream>
#include <algorithm>
#define N 2
#define MAX_R 2000
#define OFFSET 1000
using namespace std;
int x1[N], y1[N];
int x2[N], y2[N];
int checked[MAX_R + 1][MAX_R + 1];
int main() {
for(int i = 0; i < N; i++) {
cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
x1[i] += OFFSET;
y1[i] += OFFSET;
x2[i] += OFFSET;
y2[i] += OFFSET;
}
for(int i = 0; i < N; i++)
for(int x = x1[i]; x < x2[i]; x++)
for(int y = y1[i]; y < y2[i]; y++)
checked[x][y] = i + 1;
int min_x = MAX_R, max_x = 0, min_y = MAX_R, max_y = 0;
bool first_rect_exist = false;
for(int x = 0; x <= MAX_R; x++)
for(int y = 0; y <= MAX_R; y++)
if(checked[x][y] == 1) {
first_rect_exist = true;
min_x = min(min_x, x);
max_x = max(max_x, x);
min_y = min(min_y, y);
max_y = max(max_y, y);
}
int area;
if(!first_rect_exist)
area = 0;
else
area = (max_x - min_x + 1) * (max_y - min_y + 1);
cout << area;
return 0;
}
첨언
- 넓이를 구할때도 배열에 구간을 구할때처럼 x ~ x-1 해주면된다.
- 남은 구역을 덮는 사각형은 최소, 최대 행/열을 구하면 간단하다.
- 사각형1이 사각형2에 의해 완전히 가려지는 경우를 생각하지않아 한번 틀렸다.
문제를 보고 여러 케이스를 고려하고 문제를 푸는 연습이 필요하다고 느낌
작성 코드
#include <iostream>
#define A 0
#define B 1
using namespace std;
int main() {
int n, m, v, t;
int time(0), result(0), lead(-1);
int time_pos[2][1000001] = {{0,},};
cin >> n >> m;
for (int i = 0; i < n; i++){
cin >> v >> t;
for (int i = 0; i < t; i++) {
time_pos[A][time + 1] = time_pos[A][time] + v;
time++;
}
}
time = 0;
for (int i = 0; i < m; i++){
cin >> v >> t;
for (int i = 0; i < t; i++) {
time_pos[B][time + 1] = time_pos[B][time] + v;
time++;
}
}
for (int i = 0; i <= time; i++){
if (lead == -1){
if (time_pos[A][i] > time_pos[B][i]) lead = A;
else if (time_pos[A][i] < time_pos[B][i]) lead = B;
continue;
}
if (lead == B && time_pos[A][i] > time_pos[B][i]) {
lead = A;
result++;
}
else if (lead == A && time_pos[A][i] < time_pos[B][i]){
lead = B;
result++;
}
}
cout << result;
return 0;
}
해설 코드
#include <iostream>
#define MAX_T 1000000
using namespace std;
int n, m;
int pos_a[MAX_T + 1], pos_b[MAX_T + 1];
int main() {
cin >> n >> m;
int time_a = 1;
for(int i = 0; i < n; i++) {
int v, t;
cin >> v >> t;
while(t--) {
pos_a[time_a] = pos_a[time_a - 1] + v;
time_a++;
}
}
int time_b = 1;
for(int i = 0; i < m; i++) {
int v, t;
cin >> v >> t;
while(t--) {
pos_b[time_b] = pos_b[time_b - 1] + v;
time_b++;
}
}
int leader = 0, ans = 0;
for(int i = 1; i < time_a; i++) {
if(pos_a[i] > pos_b[i]) {
if(leader == 2)
ans++;
leader = 1;
}
else if(pos_a[i] < pos_b[i]) {
if(leader == 1)
ans++;
leader = 2;
}
}
cout << ans;
return 0;
}
첨언
- 배열에 A와 B의 시간에 따른 위치를 구한 뒤, 둘을 비교하여 선두가 몇번 바뀌는지 구했다.
- 알고리즘은 해설과 동일하나 가장 처음 리드하는 사람을 따로 조건걸어 구할 필요가 없었구나 싶다.
중요한 내용 : unsequenced modification and access to 'val'
time_pos[A][time] = time_pos[A][time++] + v;
우리가 배웠던 이론상으로는 time이 0이라면 아래처럼 생각할 것이다.
time_pos[A][1] = time_pos[A][0] + v;
그런데 이는 컴파일러마다 다른 값을 출력하기에 경고가 발생하는 경우가 있다.
이렇게 컴파일마다 다른 값을 출력하는 것을
-> unspeified behavior(불특정 동작)라고 한다.
아래와 같이 어떤 컴파일러를 사용하는가에 따라 값이 달라지기 않게끔 사용하는 편이 좋다.
time_pos[A][time + 1] = time_pos[A][time] + v; time++;
실제로 헷갈리기도 하니, 기왕이면 직관적으로 알 수 있는 코드를 작성하도록 노력하자.
[240722] https://github.com/mna11/codetree-TILs/tree/main/240722
[240723] https://github.com/mna11/codetree-TILs/tree/main/240723
[240724] https://github.com/mna11/codetree-TILs/tree/main/240724
[240725] https://github.com/mna11/codetree-TILs/tree/main/240725
[240726] https://github.com/mna11/codetree-TILs/tree/main/240726
[240727] https://github.com/mna11/codetree-TILs/tree/main/240727
[240728] https://github.com/mna11/codetree-TILs/tree/main/240728