제출 #1050399

#제출 시각아이디문제언어결과실행 시간메모리
1050399pawnedPaint By Numbers (IOI16_paint)C++17
100 / 100
245 ms31604 KiB
#pragma GCC optimize("O1,O2,O3,Ofast,unroll-loops") #include <bits/stdc++.h> using namespace std; #define fi first #define se second #define pb push_back typedef long long ll; typedef pair<int, int> ii; typedef vector<int> vi; #include "paint.h" vector<vector<bool>> solve(string s, vi c) { int N = s.size(); int K = c.size(); vi pfs1(N + 1, 0); // X's in prefix vi pfs2(N + 1, 0); // _'s in prefix for (int i = 1; i <= N; i++) { pfs1[i] = pfs1[i - 1]; pfs2[i] = pfs2[i - 1]; if (s[i - 1] == 'X') pfs1[i]++; if (s[i - 1] == '_') pfs2[i]++; } vector<vector<bool>> dp(N + 1, vector<bool>(K + 1, false)); // dp[i][j]: up to i (exclusive), do first j clues dp[0][0] = true; for (int i = 1; i <= N; i++) { // at s[i - 1] // cout<<"at "<<i<<endl; if (s[i - 1] != '_') { // try filled dp[i][0] = (dp[i][0] || 0); // can't have nothing for (int j = 1; j <= K; j++) { // cout<<"j: "<<j<<endl; // check if can add (j-1)st clue if (j == 1) { // no need _ to left int lb = i - c[j - 1]; // left index, all X int ub = i - 1; // right index, all X if ((lb >= 0) && (pfs1[lb] - pfs1[0] == 0) && (pfs2[ub + 1] - pfs2[lb] == 0)) dp[i][j] = (dp[i][j] || 1); } else { int lb = i - c[j - 1]; // left index, all X int ub = i - 1; // right index, all X if (lb >= 1 && pfs2[ub + 1] - pfs2[lb] == 0 && s[lb - 1] != 'X') dp[i][j] = (dp[i][j] || dp[i - c[j - 1] - 1][j - 1]); } } } if (s[i - 1] != 'X') { // try empty for (int j = 0; j <= K; j++) { dp[i][j] = (dp[i][j] || dp[i - 1][j]); } } } return dp; } string solve_puzzle(string s, vi c) { int N = s.size(); int K = c.size(); for (int i = 0; i < N; i++) { if (s[i] == '.') s[i] = '?'; } // try all combinations of _ and X // check if each works vector<vector<bool>> dp1 = solve(s, c); /* cout<<"dp1: "<<endl; for (int i = 0; i <= N; i++) { cout<<i<<": "; for (int j = 0; j <= K; j++) { cout<<dp1[i][j]<<" "; } cout<<endl; }*/ // calculate reverse dp string s2 = s; reverse(s2.begin(), s2.end()); vi c2 = c; reverse(c2.begin(), c2.end()); vector<vector<bool>> dp2 = solve(s2, c2); reverse(dp2.begin(), dp2.end()); /* cout<<"dp2: "<<endl; for (int i = 0; i <= N; i++) { cout<<i<<": "; for (int j = 0; j <= K; j++) { cout<<dp2[i][j]<<" "; } cout<<endl; }*/ // dp2[i][j]: on s[i, N - 1], true if last j can be done // check if can be blank vector<bool> can1(N, false); // can1[i] is true if s[i] can be '_' for (int i = 0; i < N; i++) { // try splitting at i for (int j = 0; j <= K; j++) { // this many to the left if (s[i] != 'X' && dp1[i][j] && dp2[i + 1][K - j]) can1[i] = true; } } /* cout<<"can1: "; for (bool b : can1) cout<<b<<" "; cout<<endl;*/ vi pfs1(N + 1, 0); // X's in prefix vi pfs2(N + 1, 0); // _'s in prefix for (int i = 1; i <= N; i++) { pfs1[i] = pfs1[i - 1]; pfs2[i] = pfs2[i - 1]; if (s[i - 1] == 'X') pfs1[i]++; if (s[i - 1] == '_') pfs2[i]++; } // check if can be filled vector<bool> can2(N, false); for (int i = 0; i < K; i++) { // considering clue i // cout<<"at "<<i<<endl; for (int j = 0; j < N - c[i] + 1; j++) { // clue starts at j // clue on [j, j + c[i] - 1] // immediate left and right must possibly be '_' bool works = true; if (j > 0 && s[j - 1] == 'X') works = false; if ((j + c[i] - 1) < N - 1 && s[j + c[i]] == 'X') works = false; // all within clue must possibly be 'X' if (pfs2[j + c[i]] - pfs2[j] != 0) works = false; if (!works) continue; // check for other clues to left and right // check for left possible bool canleft = false; if ((j == 0 && i == 0)) canleft = true; else if (j >= 1 && s[j - 1] != 'X' && dp1[j - 1][i]) canleft = true; bool canright = false; if ((j + c[i] - 1 == N - 1 && i == K - 1)) canright = true; else if (j + c[i] - 1 < N - 1 && s[j + c[i]] != 'X' && dp2[j + c[i] + 1][K - 1 - i]) canright = true; if (canleft && canright) { // actually works // cout<<"works "<<i<<" "<<j<<endl; for (int k = j; k <= j + c[i] - 1; k++) { can2[k] = true; } } } } /* cout<<"can2: "; for (bool b : can2) cout<<b<<" "; cout<<endl;*/ string ans = ""; for (int i = 0; i < N; i++) { if (can1[i] && can2[i]) // both ans += '?'; else if (can1[i]) // only empty ans += '_'; else if (can2[i]) // only filled ans += 'X'; } return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...