문제 링크
https://www.acmicpc.net/problem/2730
문제
택희는 OS조교이다. 이번 숙제는 간단히 pintos가 동작하는 화면을 캡쳐한 다음에, 이를 프린트해서 제출하는 것이다. 학생들은 보고서에 자기 학번, 이름과 제출한 날짜를 간단하게 써서 내면 된다. 어차피 올해가 몇 년인지는 모두가 알고 있기 때문에, 월/일만 적어서 내면 된다. 예를 들어, 09/20/2005 (2005년 9월 20일)이라고 쓰는 대신에 9/20이라고 쓰면 된다.
일단 채점하기 전에 과거 채점 기준을 확인하기 위해서 예전에 사람들이 냈던 보고서와 점수를 확인하고 있었다. 그런데... 올해 숙제와 예전 숙제가 섞이고 말았다. 학생들이 보고서에 연도를 쓰지 않았고, 보고서에 채점 결과를 써놓지 않았기 때문에, 보고서만 가지고는 언제 숙제인지 알수가 없게 되었다. 게다가 숙제 마감일은 매년 같다.
따라서 택희는 제출일과 숙제 마감일을 가지고 채점을 해야할지 말아야할지 결정하려고 한다.
숙제 마감일과 각 학생이 제출한 날짜가 주어졌을 때, 이것을 채점해야할지 말아야할지, 결정하는 프로그램을 작성하시오. 출력에 대한 설명은 출력 설명에 자세히 나와있다.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 둘째 줄부터 T개의 줄에는 각 테스트 케이스의 정보가 주어진다. 테스트 케이스의 정보는 날짜 2개로 이루어져 있다. 첫 번째 날짜는 숙제 마감일이고, 두 번째 날짜는 보고서에 적힌 날짜이다. 숙제 마감일은 월/일/연 형식이다. 숙제마감일은 2000년이상, 2200년 이하이고, 올바른 날짜만 주어진다. 보고서에 적힌 날짜는 월/일 형식이고, 이 날짜도 올바른 날짜만 주어진다.
출력
각 테스트 케이스에 대해서 다음과 같이 출력한다.
m/d/y IS n DAY(S) PRIOR: 보고서에 적힌 날짜가 숙제 마감일보다 7일전 이내 일 때 (같을 때는 제외)
m/d/y IS n DAY(S) AFTER: 보고서에 적힌 날짜가 숙제 마감일보다 7일후 이내 일 때 (같을 때는 제외)
SAME DAY: 보고서에 적힌 날짜와 숙제 마감일이 같을 때
OUT OF RANGE: 보고서에 적힌 날짜가 숙제 마감일보다 7일 후 또는 7일 전 안에 있지 않을 때
m/d/y는 월/일/연이고, y는 1999년 보다 크거나 같고, 2201년 보다 작거나 같다. 이때, 숙제 마감일은 매년 같기 때문에, y가 같은 필요는 없다.
예제 입력 1
7
11/20/2005 11/21
11/20/2005 11/17
11/20/2005 11/20
11/20/2005 11/13
11/20/2005 11/28
1/2/2005 12/30
12/31/2100 1/3
예제 출력 1
11/21/2005 IS 1 DAY AFTER
11/17/2005 IS 3 DAYS PRIOR
SAME DAY
11/13/2005 IS 7 DAYS PRIOR
OUT OF RANGE
12/30/2004 IS 3 DAYS PRIOR
1/3/2101 IS 3 DAYS AFTER
알고리즘 분류
- 구현
- 많은 조건 분기
풀이
많은 것을 생각해야 하는 문제였다.
우선 문자열을 Tokenize하여 숙제 마감일의 월, 일, 년도와 보고서에 작성되어 있는 날짜의 월, 일을 구한다.
그리고 숙제 마감일의 월, 일과 보고서 날짜의 월, 일을 일 단위로 바꾼다. 그러니까 3월 1일은 60, 4월 1일은 91(윤년이 아닐 때)이 되는 것이다. 근데 여기서 윤년일 때까지 따져야 한다. 윤년인지 아닌지 구하는 공식은 검색하면 나온다.
이제 숙제 마감일과 보고서 날짜의 차이를 구해서 -7일~7일, 즉 범위 안에 들면 바로 해당 문구를 출력하면 되는데 범위 밖으로 벗어났다면 숙제 마감일과 보고서 날짜의 해가 바뀌는 경우인지 아닌지를 따져야 한다. 보고서 날짜가 숙제 마감일보다 작다면 보고서 날짜의 해가 숙제 마감일보다 나중일 수 있으므로 365일을 더한다. 당해가 윤년이라면 366일을 더한다. 그리고 다시 차이를 따져서 그래도 범위 밖으로 벗어났다면 OUT OF RANGE를 출력한다. 마찬가지로 보고서 날짜가 숙제 마감일보다 크다면 보고서 날짜의 해가 숙제 마감일보다 먼저일 수 있으므로 365일을 뺀다. 당해가 윤년이라면 366일을 뺀다. 그리고 다시 차이를 따져서 그래도 범위 밖으로 벗어났다면 OUT OF RANGE를 출력한다.
코드
#include <iostream>
#include <string>
#include <cmath>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <ctime>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#include <climits>
#define FASTIO cin.tie(NULL); cout.tie(NULL); ios::sync_with_stdio(false);
#define MAX 100000000
#define LL long long
#define INF 1e9
using namespace std;
int T;
int Month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
string F, S;
void Input() {
cin >> T;
}
void Settings() {
int FM = 0;
int FD = 0;
int Year = 0;
string tmp = "";
for (int i = 0; i < F.size(); i++) {
if (F[i] == '/') {
if (FM == 0) {
FM = stoi(tmp);
}
else {
FD = stoi(tmp);
}
tmp = "";
}
else {
tmp += F[i];
}
}
Year = stoi(tmp);
int First_Date = FD;
if (FM >= 2) {
for (int i = 1; i < FM; i++) {
if (i == 2) {
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) {
First_Date += 29;
continue;
}
}
First_Date += Month[i];
}
}
int SM = 0;
int SD = 0;
tmp = "";
for (int i = 0; i < S.size(); i++) {
if (S[i] == '/') {
SM = stoi(tmp);
tmp = "";
}
else {
tmp += S[i];
}
}
SD = stoi(tmp);
int Second_Date = SD;
if (SM >= 2) {
for (int i = 1; i < SM; i++) {
if (i == 2) {
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) {
Second_Date += 29;
continue;
}
}
Second_Date += Month[i];
}
}
if (First_Date == Second_Date) {
cout << "SAME DAY\n";
}
else if (First_Date - Second_Date == -1) {
cout << S << "/" << Year << " IS 1 DAY AFTER\n";
}
else if ((First_Date - Second_Date >= -7) && (First_Date - Second_Date <= -2)) {
cout << S << "/" << Year << " IS " << -(First_Date - Second_Date) << " DAYS AFTER\n";
}
else if (First_Date - Second_Date == 1) {
cout << S << "/" << Year << " IS 1 DAY PRIOR\n";
}
else if ((First_Date - Second_Date >= 2) && (First_Date - Second_Date <= 7)) {
cout << S << "/" << Year << " IS " << First_Date - Second_Date << " DAYS PRIOR\n";
}
else {
if (First_Date > Second_Date) {
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) {
Second_Date += 366;
}
else {
Second_Date += 365;
}
if (First_Date - Second_Date == -1) {
cout << S << "/" << Year + 1 << " IS 1 DAY AFTER\n";
}
else if ((First_Date - Second_Date >= -7) && (First_Date - Second_Date <= -2)) {
cout << S << "/" << Year + 1 << " IS " << -(First_Date - Second_Date) << " DAYS AFTER\n";
}
else {
cout << "OUT OF RANGE\n";
}
}
else {
if (((Year % 4 == 0) && (Year % 100 != 0)) || (Year % 400 == 0)) {
Second_Date -= 366;
}
else {
Second_Date -= 365;
}
if (First_Date - Second_Date == 1) {
cout << S << "/" << Year - 1 << " IS 1 DAY PRIOR\n";
}
else if ((First_Date - Second_Date >= 2) && (First_Date - Second_Date <= 7)) {
cout << S << "/" << Year - 1 << " IS " << First_Date - Second_Date << " DAYS PRIOR\n";
}
else {
cout << "OUT OF RANGE\n";
}
}
}
}
void Find_Answer() {
while (T--) {
cin >> F >> S;
Settings();
};
}
int main() {
FASTIO
Input();
Find_Answer();
return 0;
}
'BOJ > Silver' 카테고리의 다른 글
[BOJ/Silver 3] 백준 1735 분수 합(C++) (0) | 2022.06.08 |
---|---|
[BOJ/Silver 3] 백준 25239 가희와 카오스 파풀라투스(C++) (0) | 2022.06.06 |
[BOJ/Silver 3] 백준 11332 시간초과(C++) (0) | 2022.05.26 |
[BOJ/Silver 5] 백준 21966 (중략)(C++) (0) | 2022.05.26 |
[BOJ/Silver 3] 백준 1614 영식이의 손가락(C++) (0) | 2022.05.26 |