結果
| 問題 | No.291 黒い文字列 |
| コンテスト | |
| ユーザー |
norioc
|
| 提出日時 | 2025-11-29 16:18:00 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 119 ms / 2,000 ms |
| コード長 | 3,460 bytes |
| コンパイル時間 | 3,629 ms |
| コンパイル使用メモリ | 287,500 KB |
| 実行使用メモリ | 7,716 KB |
| 最終ジャッジ日時 | 2025-11-29 16:18:06 |
| 合計ジャッジ時間 | 5,950 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 26 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
static const int CAP = 20;
static const int INF = -1000000000;
struct Key { int k,u,r,o; };
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
string S;
if(!(cin >> S)) return 0;
static int dp[21][21][21][21];
static int pp[21][21][21][21];
auto in_range = [&](int a,int b,int c,int d){
return (0<=a && a<=CAP &&
0<=b && b<=CAP &&
0<=c && c<=CAP &&
0<=d && d<=CAP);
};
// init
for(int k=0;k<=CAP;k++)
for(int u=0;u<=CAP;u++)
for(int r=0;r<=CAP;r++)
for(int o=0;o<=CAP;o++)
dp[k][u][r][o] = INF;
dp[0][0][0][0] = 0;
vector<Key> cur;
cur.reserve(10000);
cur.push_back({0,0,0,0});
// used array reused each iteration
static bool used[21][21][21][21];
for(char c : S){
// pp = dp (copy)
memcpy(pp, dp, sizeof(dp));
// dp = pp (keep carry-over)
memcpy(dp, pp, sizeof(dp));
// reset used and mark current cur as used (so we don't add duplicates)
memset(used, 0, sizeof(used));
for(const auto &st : cur){
used[st.k][st.u][st.r][st.o] = true;
}
vector<Key> nxt;
nxt.reserve(10000);
auto push = [&](int a,int b,int c2,int d,int v){
if(!in_range(a,b,c2,d)) return;
if(dp[a][b][c2][d] < v){
dp[a][b][c2][d] = v;
}
if(!used[a][b][c2][d]){
used[a][b][c2][d] = true;
nxt.push_back({a,b,c2,d});
}
};
// iterate only keys that were active in pp (represented by cur)
for(const auto &st : cur){
int k = st.k, u = st.u, r = st.r, o = st.o;
int val = pp[k][u][r][o];
if(val == INF) continue; // safety
if(c == 'K'){
push(k+1, u, r, o, val);
} else if(c == 'U'){
push(k-1, u+1, r, o, val);
} else if(c == 'R'){
push(k, u-1, r+1, o, val);
} else if(c == 'O'){
push(k, u, r-1, o+1, val);
} else if(c == 'I'){
if(o > 0) push(k, u, r, o-1, val + 1);
}
if(c == '?'){
push(k+1, u, r, o, val);
push(k-1, u+1, r, o, val);
push(k, u-1, r+1, o, val);
push(k, u, r-1, o+1, val);
if(o > 0) push(k, u, r, o-1, val + 1);
}
}
// **重要な修正**: cur を nxt で置換せず、cur に nxt を追加して「和集合」にする
// こうすることで次の反復で pp.keys() に相当する dp 中の全キーを走査できます。
if(!nxt.empty()){
cur.insert(cur.end(), nxt.begin(), nxt.end());
// Optional: if cur grows too large, you can periodically compact it
// by rebuilding cur from dp (scan dp for != INF). But typically not needed.
}
// note: we intentionally keep earlier cur entries (carry-over states),
// because dp = pp preserved them and Python would iterate them next round as well.
}
int ans = 0;
for(int k=0;k<=CAP;k++)
for(int u=0;u<=CAP;u++)
for(int r=0;r<=CAP;r++)
for(int o=0;o<=CAP;o++)
ans = max(ans, dp[k][u][r][o]);
cout << ans << "\n";
return 0;
}
norioc