POJ 3126 Prime Path(素數,BFS最短路)
阿新 • • 發佈:2018-11-01
【連結】http://poj.org/problem?id=3126
【題意】給個字串,求滿足形如“E...E...E”這種鬼樣子的E串最大長度,其中“...”可以是任意個數的任意字元(沒有也ok),但是三個E之間不能重疊
【思路】
① 掏出素數篩的模板,找到1W以內素數
② 留下1000~9999之間的儲存在prime[],用個map記錄一下下標
③ 因為一起也就2000多點素數,n^2處理一下之間是否可以一步到達,用vector<int>的陣列存下鄰接表
④ 讀素數,mp出下標,最基礎的BFS來一發找出最短路(調1個數字就能轉換的數之間距離為1)就是了
【程式碼】作大死,套了半天dijkstra調不好還妄圖使用spfa最後還是老老實實bfs一下……
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <iostream> #include <map> #include <vector> #include <set> #include <queue> #include <stack> #include <algorithm> using namespace std; #define MAX_LEN 2100 #define ll long long #define mod 100000007 #define MEM(a,al) memset(a,al,sizeof(a)) #define sfx(x) scanf("%lf",&x) #define sfxy(x,y) scanf("%lf%lf",&x,&y) #define sdx(x) scanf("%d",&x) #define sdxy(x,y) scanf("%d%d",&x,&y) #define pfx(x) printf("%.0f\n",x) #define pfxy(x,y) printf("%.6f %.6f\n",x,y) #define pdx(x) printf("%d\n",x) #define pdxy(x,y) printf("%d %d\n",x,y) #define getArray(a,len) for(int ia = 0; ia < len; ia++) scanf("%d",&a[ia]) #define printArray(a,len) for(int ia = 0; ia < len; ia++) printf("%d%c",a[ia],(ia==len-1)?'\n':' ') #define fora(i,n) for(i = 0; i < n; i++) #define fora1(i,n) for(i = 1; i <= n; i++) #define foraf(i,n) for(int i = 0; i < n; i++) #define foraf1(i,n) for(int i = 1; i <= n; i++) #define ford(i,n) for(i = n-1; i >= 0; i--) #define ford1(i,n) for(i = n; i > 0; i--) #define fordf(i,n) for(int i = n-1; i >= 0; i--) #define fordf1(i,n) for(int i = n; i > 0; i--) class WriteInfo{ public: void info() { printf("[Info] "); } void infoEnd() { printf(" [/Info]\n"); } } W; const int INF = 1<<29; const double INFD = 1e20; const double eps = 1e-6; int n,m,a,b; map< int, int > mp; vector< int > v[MAX_LEN]; int prime[MAX_LEN]; // 素數篩選,素數存放於st (此模板來源於網路……) set<int> st; #define MAX_P 10000 int nList[MAX_P] = {0}; void Calc() { int n,p,t,sq=(int)sqrt(MAX_P*2+1); for (n=3;n<=sq;n+=2) { if (nList[n>>1]) continue; for (t=n*n;t<=MAX_P<<1;t+=n<<1) //篩選迴圈 nList[t>>1] = 1; } st.insert(2); for (n=t=1;t<MAX_P;++t) { if (nList[t]) continue; st.insert((t<<1)+1); if (++n==10) n=0; } } bool check(int x, int y){ int res = 0; while(x){ if (x%10 == y%10) res++; x /= 10; y /= 10; } return (res == 3); } int bfs(int x, int y){ if (x == y) return 0; int dis[MAX_LEN]; MEM(dis, -1); queue< int > q; q.push(x); dis[x] = 0; while(!q.empty()){ int p = q.front(); q.pop(); foraf(i,v[p].size()){ int next = v[p][i]; if (next == y) return dis[p] + 1; if (dis[next] == -1){ q.push(next); dis[next] = dis[p] + 1; } } } return -1; } int main() { int i,j,k; int T; // 掏來的模板篩素數,放到mp裡對映一下儲存prime陣列中的下標 Calc(); mp.clear(); int co = 0; for(set< int >::iterator it = st.begin(); it != st.end(); it++){ if (*it > 1000 && *it < 10000){ mp[*it] = co; prime[co++] = *it; } } // 預處理,總共也就2000+個素數 fora(i,co) for(j = i+1; j < co; j++) if (check(prime[i],prime[j])){ v[i].push_back(j); v[j].push_back(i); } sdx(T); while(T--){ sdxy(a,b); // 直接用下標來做 int res = bfs(mp[a], mp[b]); if (res != -1) pdx(res); else puts("Impossible"); } return 0; }
為寫一篇日誌做了整整一個月半的心理準備【滾!