Link: http://www.spoj.com/problems/PPATH/
Hiểu đề PPATH spoj
Bạn đuợc cho 2 số nguyen tố 4 chữ số. Việc của bạn là tìm số bước ngắn nhất để biến số nguyen tố thứ 1 thành số thứ 2.
Quy định rang trong mỗi bước bạn chỉ đổi được 1 trong 4 chữ số của số thứ 1 để đợợc 1 số nguyen tố mới. Cứ thế tiếp diễn cho tới khi nào thành số thứ 2.
Ví du: 1033 -> 1733 -> 3733 -> 3739 -> 3779 -> 8779 -> 8179. (không được chuyển chữ số đầu tiên thành chữ số 0). Nếu không tìm được thì xuất ra “Impossible”.
Gợi ý giải PPATH spoj
Sử dung BFS và Sieve of Eratosthenes. ( chi tiết mình note trong code bên dưới).
#include<iostream> #include<queue> #include<string.h> #define max 10005 using namespace std; int T, s, d, digit[4]; int prime[max], dist[max]; // mảng prime đánh dấu số nào là số nguyên tố ( snt:-1 và ko là snt: 0) // mảng dist để lưu số bước void sieve() // để đánh dấu các số nt trong mảng prime { for (int i = 2; i < 10000; i++) { if (prime[i]) { int num = i; for (int j = 2; num*j <=max; j++) prime[num*j] =0; } } } void num_to_arr(int value[], int num)// chuyển 4 chữ số vào mảng { for (int i = 3; i >= 0; i--) { value[i] = num % 10; num /= 10; } } int arr_to_num(int value[])// từ mảng ra số { int res = 1000 * value[0] + 100 * value[1] + 10 * value[2] + value[3]; return res; } int main() { memset(prime, -1, sizeof(prime)); sieve(); cin >> T;//test case while (T--) { cin >> s >> d; memset(dist, -1, sizeof(dist)); queue<int> q; q.push(s); dist[s] = 0; while (!q.empty()) { s = q.front(); q.pop(); for (int i = 0; i <= 3; i++)// cố định 3 chữ số rồi chạy 3 chữ số còn lại để xét { num_to_arr(digit, s); for (int j = 0; j <= 9; j++) { digit[i] = j; int temp = arr_to_num(digit); if (prime[temp] == -1 && temp > 1000 && dist[temp] == -1)// nếu số đó chưa đc xét và là snt thì đánh dấu số bước. { dist[temp] = dist[s] + 1; q.push(temp); } } } } if (dist[d] == -1) cout << "Impossible" << endl; else cout << dist[d] << endl; } return 0; }