Test instructions: There are m switches in a machine, each switch represents a number between 0 0~ 2n−1 2^n-1, and there are only three 1 in the binary representation of each number. The result of a number Y through M switches is:
Y⊕x1⊕x2⊕ ... ⊕XM Y \oplus x_1 \oplus x_2\oplus ... \oplus x_m
Now give the initial number s, and the target number T, want to use the smallest number of switches, so that s into T, to find the minimum number of switches. If output is not possible, impossible.
Idea: The method of finding the smallest steps has many, the shortest circuit on the graph, BFS,IDA*,A*DP;
However, test instructions is prompted: warning:a naive algorithm might not being sufficient to solve this problem. That's basically the negation: the shortest circuit on the chart, the BFS,DP, because the complexity of the three is very high.
So, it looks like you can only use ida* and a *
Ida* is simpler in terms of programming complexity, so let's consider using ida* first.
In ida*, the most critical is the design of the heuristic function H ().
First, notice that each switch is used at most once. It is useless to use two times or so. This is clear, in search of me, we search directly backwards, without backtracking.
Then, notice that the topic tells the binary expression of each switch to have only 3 1.
In this way, we can find out how many bits of the current number z and the target T are different, as the arguments of the H function.
The most important content is the design of the H function, because there is no weight in the ida*, there must be an efficient heuristic function h, so that the search to reach the target State faster.
So, we ask for two binary numbers with different I bits, at least how many switches are needed to change from one to the other, and this is our heuristic function h, which can be used for brute force
In this way, we have finished the design of ida*.
There is also a more important question, under what circumstances is the impossible situation. if m switches are searched, but no solution is found, this indicates that the impossible is the case.
The code is as follows:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std;
int n,m,s,t;
int h[]={0,3,2,1,2,3,2,3,4,3,4,5,4,5,6,5,6,7,6,7,8};
int p[1<<21];
int v[1<<21];
int count (int x) {x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f);
x = (x & 0x00ff00ff) + ((x >> 8) & 0X00FF00FF);
x = (x & 0x0000ffff) + ((x >> +) & 0x0000ffff);
return x;
} bool Dfs (int state,int id,int d, int maxd) {if (d = = Maxd && state = = T) return true; if (h[p[state ^ T]] + d > Maxd | |
M-id + D < maxd) return false;
for (int i = ID; i < M; ++i) if (Dfs (state ^ v[i],i+1,d+1,maxd)) return true;
return false;
} int main (void) {//freopen ("Input.txt", "R", stdin);
int cas = 1; for (int i = 0; I <1100000; ++i) p[i] = Count (i); while (scanf ("%d%d", &n,&m), n| |
M) {scanf ("%d%d", &s,&t);
for (int i = 0; i < M; ++i) scanf ("%d", &v[i]);
int dep = 0;
BOOL sig = false;
For (;d EP <= M;++DEP) {if (Dfs (S,0,0,DEP)) {sig = true;
Break
}} printf ("Case #%d:", cas++);
if (SIG) printf ("%d\n", DEP);
Else puts ("impossible");
} return 0; }