結果
問題 |
No.3121 Prime Dance
|
ユーザー |
|
提出日時 | 2025-04-24 15:52:30 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,039 bytes |
コンパイル時間 | 2,621 ms |
コンパイル使用メモリ | 214,100 KB |
実行使用メモリ | 7,848 KB |
最終ジャッジ日時 | 2025-04-24 15:52:34 |
合計ジャッジ時間 | 3,881 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 8 WA * 13 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int H, W, Sx, Sy, Gx, Gy; cin >> H >> W >> Sx >> Sy >> Gx >> Gy; vector<string> C(H); for (auto &s : C) cin >> s; auto in = [&](int x,int y){ return 0<=x && x<H && 0<=y && y<W; }; const int dx4[4]={1,-1,0,0}, dy4[4]={0,0,1,-1}; /* 1) S→G の最短距離 L0 と可到達成分を求める */ vector<vector<int>> dist(H, vector<int>(W,-1)); queue<pair<int,int>> q; dist[Sx-1][Sy-1]=0; q.emplace(Sx-1,Sy-1); while(!q.empty()){ auto [x,y]=q.front(); q.pop(); for(int d=0; d<4; d++){ int nx=x+dx4[d], ny=y+dy4[d]; if(!in(nx,ny) || C[nx][ny]=='#' || dist[nx][ny]!=-1) continue; dist[nx][ny]=dist[x][y]+1; q.emplace(nx,ny); } } int L0 = dist[Gx-1][Gy-1]; if(L0==-1){ cout<<-1<<"\n"; return 0; } /* 2) 成分内に縦/横エッジがあるか */ bool adjV=false, adjH=false; for(int i=0;i<H;i++)for(int j=0;j<W;j++)if(dist[i][j]!=-1){ if(i+1<H && dist[i+1][j]!=-1) adjV=true; if(j+1<W && dist[i][j+1]!=-1) adjH=true; } int dx = Gx-Sx, dy = Gy-Sy; int dv = abs(dx), dh = abs(dy); if(dv==0 && !adjV){ cout<<-1<<"\n"; return 0; } if(dh==0 && !adjH){ cout<<-1<<"\n"; return 0; } /* 3) 十分大きい範囲で素数表を作る */ const int PMAX = L0 + dv + dh + 100; // 余裕を持たせる vector<char> isP(PMAX+1,1); isP[0]=isP[1]=0; for(int i=2;i*i<=PMAX;i++) if(isP[i]) for(int j=i*i;j<=PMAX;j+=i) isP[j]=0; vector<int> primes; primes.reserve(PMAX/10); for(int i=2;i<=PMAX;i++) if(isP[i]) primes.push_back(i); auto prime = [&](int x){ return x>1 && x<=PMAX && isP[x]; }; /* 4) 縦/横それぞれ「条件を満たす2素数の和」を列挙 */ vector<int> sumV, sumH; if(dx>=0){ for(int A:primes){ int B=A-dx; if(B>0 && prime(B)) sumV.push_back(A+B); } }else{ for(int B:primes){ int A=B-dx; if(A>0 && prime(A)) sumV.push_back(A+B); } } if(dy>=0){ for(int Cc:primes){ int D=Cc-dy; if(D>0 && prime(D)) sumH.push_back(Cc+D); } }else{ for(int D:primes){ int Cc=D-dy; if(Cc>0 && prime(Cc)) sumH.push_back(Cc+D); } } if(sumV.empty() || sumH.empty()){ cout<<-1<<"\n"; return 0; } /* ループが挿入できない方向は最小値だけで十分 */ if(!adjV) sumV = { *min_element(sumV.begin(), sumV.end()) }; if(!adjH) sumH = { *min_element(sumH.begin(), sumH.end()) }; sort(sumV.begin(), sumV.end()); sort(sumH.begin(), sumH.end()); /* 5) v+h ≥ L0 を満たす最小値を二分探索で求める */ int ans = INT_MAX; for(int v : sumV){ int need = L0 - v; auto it = lower_bound(sumH.begin(), sumH.end(), max(need,0)); if(it!=sumH.end()) ans = min(ans, v + *it); } if(ans==INT_MAX) ans = -1; cout << ans << '\n'; return 0; }