結果
| 問題 |
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;
}