A. Minimum Binary Number



처음 문제를 봤을 때 operation을 1번이나 제한적으로 쓸 수 있다고 생각해서 A 부터 엄청 어려운 게 나왔구나 했는데 계속 사용이 가능했다. 보면 나올 수 있는 최소의 값은 0의 개수를 세어주고 그 뒤에 1을 붙이거나, input이 1 0 인 예외를 처리해주면 통과되었다. 

#include <iostream>
#include <string>
using namespace std;
char arr[1001];
int main(void) {
       int n;
       cin >> n;
       string s;
       cin >> s;
       if (n == 1 && s[0] == '0') {
               cout << '0' << endl;
               return 0;
       }
       int cnt = 0;
       for (int i = 0; i < n; ++i) {
               if (s[i] == '0') {
                      cnt++;
               }
       }
       cout << '1';
       for (int i = 0; i < cnt; ++i) {
               cout << '0';
       }
       return 0;
}



B. Lara Croft and the New Game


처음 문제를 봤을 때 x좌표와 y좌표를 k,n,m에 대해서 나타낼 수 있을 걸 알았지만 교육적인 목적에서 직접 경로를 탐색하는 코드를 짜보았다. 무슨 생각인 진 모르겠지만 k가 10^9보다 작다고 생각해서 시간초과는 안 날 것이라 생각했는데 짜놓고 제출하고 시간초과가 나서 생각해보니 최악의 경우 INT32_MAX-1까지 가능했다. 20억번이므로 대략 20초가 걸리므로 당연히 시간초과
그래도 구현한 코드를 올려보면 

#include <iostream>
#include <string>
using namespace std;
int c;
int x = 1, y = 1;
bool inturrupt() {
       if (x == 1 && y == 2) {
               cout << x << ' ' << y << endl;
               return 1;
       }
       if (c == 0) {
               cout << x << ' ' << y << endl;
               return 1;
       }
       c--;
       return false;
};
void print() {
       cout << x << ' ' << y << endl;
}
int main(void) {
       int a, b;
       cin >> a >> b >> c;
       a--;
       b--;
       //print();
       if (inturrupt()) {
               return 0;
       }
       
       for (int i = 1; i <= a; ++i) {
               x++;
               if (inturrupt()) {
                      return 0;
               }
               //print();
       }
       for (int i = 1; i <= b; ++i) {
               y++;
               if (inturrupt()) {
                      return 0;
               }
               //print();
       }
       while (c != 0) {
               x--;
               if (inturrupt()) {
                      return 0;
               }
//print();
               for (int i = 1; i <= b - 1; ++i) {
                      y--;
                      if (inturrupt()) {
                              return 0;
                      }
               //     print();
               }
               x--;
               if (inturrupt()) {
                      return 0;
               }
               //print();
               for (int i = 1; i <= b - 1; ++i) {
                      y++;
                      if (inturrupt()) {
                              return 0;
                      }
               //     print();
               }
       }
       return 0;
}

inturrupt 함수는 한번 x나 y를 바꾸는 연산을 한 다음에 실행시켜 줘서 k가 0이 되면 x,y를 출력하고 끝내도록 만들었다. 코드는 엄청 복잡했다. 

#include <iostream>
#include <string>
using namespace std;
int c;
int x = 1, y = 1;
int main(void) {
       int n, m;
       cin >> n >> m >> c;
       if (c < n) {
               cout << 1 + c << ' ' << 1 << endl;
               return 0;
       }
       if (c < n + m - 1) {
               cout << n << ' ' << (c - (n - 1)) + 1 << endl;
               return 0;
       }
       if (n*m - 1 == c) {
               cout << 1 << ' ' << 2 << endl;
               return 0;
       }
       c -= (m + n - 2);
       int temp = n - 1 - ((c-1) / (m - 1));
       int temp2;
       if (temp % 2 == 0) {
               temp2 = 1 + (c-1) % (m - 1);
       }
       else {
               temp2 =  m - 1 - (c-1) % (m - 1);
       }
       cout << temp << ' ' << temp2 + 1 << endl;
       return 0;
}

x와 y를 n,m,k에 대한 식으로 나타내서 짠 코드. 여기서 
Note that k doesn't fit into 32-bit integer type!
이런 문구가 있는 걸 간과했다. long long 으로 작성하면 accept를 받을 수 있었다. 



C. Nested Segments


뻔한 문제 같은데 도저히 풀 방법이 생각나지 않았다. Contest 가 끝나고 나서 코드를 확인해 보니

좌표를 묶어서 first 크기대로 정렬을 한다. first가 같으면 second가 작은 순으로 정렬한다. 

본래 순서의 index를 가지고 있어야 하므로 index배열을 따로 만들고 index배열을 정렬시키면서 정럴시키는 cmp 함수안의 조건은 pair값을 사용한다. 

정렬이 끝나면 첫번째 값은 무조건 다음값에 포함되므로 생각하지 않고 second 값만 비교한다. 

#include <iostream>
#include <algorithm>
using namespace std;
int u[300001];
pair<int, int> in[300001];
int main(void)
{
       int n;
       cin >> n;
       for (int i = 1; i <= n; ++i) {
               u[i] = i;
               cin >> in[i].first >> in[i].second;
       }
       sort(u + 1, u + n + 1, [](int a, int b) {
               if (in[a].first != in[b].first) {
                      return in[a].first < in[b].first;
               }
               else {
                      return in[a].second > in[b].second;
               }
       });
       int temp = u[1];
       for (int i = 2; i <= n; ++i) {
               if (in[temp].second >= in[u[i]].second) {
                      cout << u[i] << ' ' << temp << endl;
                      return 0;
               }
               else {
                      temp = u[i];
               }
       }
       cout << -1 << ' ' << -1 << endl;
       return 0;
}




A. Splits

A 번 문제가 아니었다면 못풀었을 것 같다. 
A라 분명 쉬울껀데 하면서 계속 해보니까 
결국 중요한 건 맨 앞에 오는 숫자의 개수이고 뒤는 1로 다 채워버려도 됐다. 
어떤 숫자가 n이라면

n개를 다 1로 채우는 방법,
n개에서 한개를 2로하고 나머지를 1로 채우는 방법
n개에서 2개를 2로하고 나머지를 1로 채우는 방법

... 

n개에서 n/2개를 2로하고 나머지가 있다면 1로 두는 방법 으로 구할 수 있다.

따라서 모든 방법의 수는 n/2+1

#include <iostream>
using namespace std;
int main(void)
{
       int n;
       cin >> n;
       cout << n / 2 + 1;
       return 0;
}



B. Messages


브루트포스로 풀었다. 

편지를 안 읽고 두냐, 아니면 얼른 읽어버리냐의 최대값의 차이는 

(t-ti)*c + (a-b*(t-ti))

이런 수식으로 구할 수 있었다. ti를 편지를 받은 tb[i] 부터 끝까지 가지고 있는 <= t 로 범위를 준 후 다 해본다음의 max 값을 ans 에 더해줘서 구했다. 

이게 될까 싶었는데 돌려보니 바로 Accept 가 떠서 신기했다. 

#include <iostream>
#include <algorithm>
using namespace std;
int tb1[100001];
int main(void)
{
       int n, a, b, c, t;
       cin >> n >> a >> b >> c >> t;
       for (int i = 0; i<n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i<n; ++i) {
              int tmax = 0;
              for (int ti = tb1[i]; ti <= t; ++ti) {
                     int temp = (t - ti)*c + (a - b * (t - ti));
                     tmax = max(tmax, temp);
              }
              ans += tmax;
       }
       cout << ans << endl;
       return 0;
}






한시간 동안 풀었는데 결국 풀지 못했다. 

[2 3 1]

의 뜻이 뭔지 이해가 안 되었던게 컸던 것 같다. 

처음에 생각했던 것은 tetris 니까 n개의 블록을 잘 내려서 줄을 없애라는 줄 알았다. 

이렇게 하면 1개가 있는 자리에 n개의 블록을 1개씩 보내주면 모두 2개 이상이 되어 두 줄을 없앨 수 있어서 

2가 답인 줄 알았다. 

해석할 때 시간이 오래 걸릴 것 같아 파파고번역기로 번역을 해서 한게 좋지 않은 영향을 준 것 같다. 

실제 문제는 Hack 단계에서 다른 사람의 코드를 보니 3개의 열이 있고 주어진 블록을 해당열에다가 쌓는 형식이었다.

문제만 제대로 이해했으면 금방 풀었을 텐데 아쉽다. 

Accept 받은 코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
int che[100001];
bool doo[100001];
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < m; ++i) {
              int k;
              cin >> k;
              tb1[k]++;
       }
       int ans = INT32_MAX;
       for (int i = 1; i <= n; ++i) {
              ans = min(ans, tb1[i]);
       }
       cout << ans << endl;
       return 0;
}



B. Lecture Sleep


주인공은 잠이 많아 수업시간에 조는데 깨어있는 동안은 열심히 적는다. 

단 한번 깨울 수 있는데 깨우면 m분만큼 필기를 한다.

 최대한 많이 필기 하는 양을 출력

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
bool che[100001];
bool doo[100001];
stack<int> st;
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     st.push(i);
                     ans += tb1[i];
              }
       }
       
       int tempansmax = 0;
       for (int i = 0; i < n-m+1; ++i) {
              int tempans = ans;
              for (int k = i; k < i + m; ++k) {
                     if (che[k] == 0) {
                           tempans += tb1[k];
                     }
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}

Time Out 날 걸 확신하고 쓴 코드. 
 for (int k = i; k < i + m; ++k) {
                     if (che[k] == 0) {
                           tempans += tb1[k];
                     }
              }
이 코드를 조금 만 더 최적화 하면 될 것 같다. 

바뀌는 부분은 맨 처음과 맨 끝이므로 
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
bool che[100001];
bool doo[100001];
stack<int> st;
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     st.push(i);
                     ans += tb1[i];
              }
       }
       int tempans = ans;
       int tempansmax = 0;
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m - 1] == 0) {
                     tempans += tb1[i + m - 1];
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}
이렇게 수정을 했는데 TC4에서 Wrong answer 이 나왔다. 

int tempans = ans;
       int tempansmax = 0;
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m - 1] == 0) {
                     tempans += tb1[i + m - 1];
              }
              tempansmax = max(tempansmax, tempans);
       }

여기서 tempansmax가 for(int i=1 로 들어가기 전에 k=0~m 까지 더한 값을 저장하고 가야 하는데 놔두고 가서 TC4가
k=0에서 시작해서 하는게 최대값인 경우라 Wrong Answer 이었다 보다


Accept 받은 코드
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <limits.h>
#include <queue>
#include <stack>
using namespace std;
int tb1[100001];
int che[100001];
bool doo[100001];
int n, m;
int main(void)
{
       cin >> n >> m;
       
       for (int i = 0; i < n; ++i) {
              cin >> tb1[i];
       }
       int ans = 0;
       for (int i = 0; i < n; ++i) {
              int k;
              cin >> k;
              che[i] = k;
              if (k == 1) {
                     ans += tb1[i];
              }
       }
       int tempans = ans;
       
       for (int k = 0; k < m; ++k) {
              if (che[k] == 0) {
                     tempans += tb1[k];
              }
       }
       int tempansmax = tempans;
       for (int i = 1; i < n-m+1; ++i) {
              if (che[i - 1] == 0) {
                     tempans -= tb1[i - 1];
              }
              if (che[i + m-1] == 0) {
                     tempans += tb1[i + m-1];
              }
              tempansmax = max(tempansmax, tempans);
       }
       cout << tempansmax << endl;
       return 0;
}


+ Recent posts