結果
問題 |
No.3121 Prime Dance
|
ユーザー |
|
提出日時 | 2025-04-20 13:09:27 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 4,805 bytes |
コンパイル時間 | 2,841 ms |
コンパイル使用メモリ | 213,948 KB |
実行使用メモリ | 7,848 KB |
最終ジャッジ日時 | 2025-04-20 13:09:31 |
合計ジャッジ時間 | 4,221 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 4 WA * 17 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; /* ---------- 素数テーブル ---------- */ struct PrimeTable { int N; vector<int> primes; vector<char> isPrime; PrimeTable(int n = 20000) { build(n); } void build(int n) { N = n; isPrime.assign(N + 1, 1); isPrime[0] = isPrime[1] = 0; for (int i = 2; i * 1LL * i <= N; ++i) if (isPrime[i]) for (int j = i * i; j <= N; j += i) isPrime[j] = 0; for (int i = 2; i <= N; ++i) if (isPrime[i]) primes.push_back(i); } bool operator()(int x) const { return 0 <= x && x <= N && isPrime[x]; } } primeTbl(40000); // 上限 4 万で十分 /* ---------- BFS で最短距離 ---------- */ const int INF = 1e9; int bfsDist(const vector<string>& G, int sx, int sy, vector<vector<int>>& dist) { const int H = G.size(), W = G[0].size(); dist.assign(H, vector<int>(W, INF)); queue<pair<int,int>> q; dist[sx][sy] = 0; q.emplace(sx, sy); const int dx[4]={1,-1,0,0}, dy[4]={0,0,1,-1}; while(!q.empty()){ auto [x,y]=q.front(); q.pop(); for(int dir=0;dir<4;++dir){ int nx=x+dx[dir], ny=y+dy[dir]; if(nx<0||nx>=H||ny<0||ny>=W) continue; if(G[nx][ny]=='#'||dist[nx][ny]!=INF) continue; dist[nx][ny]=dist[x][y]+1; q.emplace(nx,ny); } } return 0; // 呼び出し側で dist[Gx][Gy] を見る } /* ---------- 2 ステップ縦(or 横)ループがあるか ---------- */ bool hasStraightLoop(const vector<string>& G, const vector<vector<int>>& dist, bool vertical){ // true→縦, false→横 const int H = G.size(), W = G[0].size(); int dx = vertical ? 1 : 0; int dy = vertical ? 0 : 1; for(int x=0;x<H;++x)for(int y=0;y<W;++y){ if(dist[x][y]==INF) continue; // 到達不能 int nx=x+dx, ny=y+dy; if(nx<0||nx>=H||ny<0||ny>=W) continue; if(G[nx][ny]!='#'&&dist[nx][ny]!=INF) return true; } return false; } /* ---------- 差分 Δ に対する候補和列を作る ---------- */ vector<int> buildSumList(int diff, bool loopAble, int maxPrime = 40000, int maxExtra = 2000){ vector<int> sums; const auto& isP = primeTbl.isPrime; const auto& primes = primeTbl.primes; if (diff >= 0){ for(int q: primes){ int p = q + diff; if(p>maxPrime) break; if(!isP[p]) continue; // k=0 は必ず sums.push_back(p+q); if(loopAble){ int k = 1; while(2*k <= maxExtra){ if(p+k>maxPrime || q+k>maxPrime) break; if(isP[p+k] && isP[q+k]) sums.push_back(p+q+2*k); ++k; } } } }else{ // diff < 0 for(int p: primes){ int q = p - diff; // q > p if(q>maxPrime) break; if(!isP[q]) continue; sums.push_back(p+q); if(loopAble){ int k = 1; while(2*k <= maxExtra){ if(p+k>maxPrime || q+k>maxPrime) break; if(isP[p+k] && isP[q+k]) sums.push_back(p+q+2*k); ++k; } } } } sort(sums.begin(), sums.end()); sums.erase(unique(sums.begin(), sums.end()), sums.end()); return sums; } /* ---------- メイン ---------- */ int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int H,W; cin>>H>>W; int Sx,Sy,Gx,Gy; cin>>Sx>>Sy>>Gx>>Gy; --Sx;--Sy;--Gx;--Gy; vector<string> G(H); for(auto& s:G) cin>>s; /* --- 最短距離 & 到達判定 --- */ vector<vector<int>> dist; bfsDist(G,Sx,Sy,dist); int D = dist[Gx][Gy]; if(D==INF){ cout<<-1<<"\n"; return 0; } int dx = Gx - Sx; int dy = Gy - Sy; /* --- ループ判定 --- */ bool vLoop = hasStraightLoop(G,dist,true); bool hLoop = hasStraightLoop(G,dist,false); /* --- 差分ごとの候補和列 --- */ auto vSums = buildSumList(dx, vLoop); auto hSums = buildSumList(dy, hLoop); if(vSums.empty() || hSums.empty()){ cout<<-1<<"\n"; return 0; } /* --- 二列マージで最小和 ≥ D --- */ int ans = INT_MAX; for(int sv: vSums){ int need = D - sv; if(need <= 0){ ans = min(ans, sv + hSums.front()); continue; } auto it = lower_bound(hSums.begin(), hSums.end(), need); if(it!=hSums.end()){ ans = min(ans, sv + *it); } } if(ans==INT_MAX) ans=-1; cout<<ans<<"\n"; return 0; }