Title Description
"Topic Background"
Small X is trapped in a secret room, and he hopes to escape from the chamber as soon as possible.
There are n rooms in the chamber, initially, the small X is in room 1th, and exits in room N.
Each room in the Chamber of Secrets may have some keys and some portals, and a portal will create a one-way path from room X to room Y. In addition, if you want to pass a portal, you must have some kind of key. Fortunately, the key does not disappear after the seal of the portal is opened.
However, it takes a lot of time to pass through the door of the chamber, so small x wants to reach the exit with as few portals as possible, can you tell the value of the small x?
In addition, the small X may not escape from the chamber, if so, please output "No solution". input
The first line three integers N, M, K, respectively, indicating the number of rooms, the number of portals and the number of key types.
The next N rows, each row K 0 or 1, if the number of the first is 1, then the room has a key I, if the number of 0, then the room does not have the key I type.
Next M line, each line is read into two integer x, Y, indicating that the portal is built in the X room, leading to the room Y, and then read into K 0 or 1, if the number of 1, if I have a key is required through the portal, if the number of I is 0, it means that the portal does not require the key I type 。 Output
Output a line of "No solution", or an integer that represents the minimum number of passes. Sample Input
3 3 2
1 0
0 1
0 0
1 3 1 1
1 2 1 0
2 3 1 1
Sample Output
2
Tips
More examples: Download
Exercises
"Test points 1-3, 11, 12, 15, 18" Note that N and M are small, direct search can be, in the search at the same time record the current collection of keys. But if there is a loop in the graph, the search may lead to a dead loop. The solution is to search for a certain number of steps to exit, found no solution. (* Pruning: If the number of steps is greater than the current optimal answer, you can exit the search)
"Test point 1-10" K = 0, the problem becomes a 1 to N of the shortest, with a shortest-path algorithm can be.
Floyd algorithm, time complexity O (N3), can only pass test point 1-6.
Dijkstra algorithm, Time complexity O (N2)-O (N * Log N), can pass test point 1-10.
SPFA algorithm, Time complexity O (N * M)-O (M), can pass test point 1-10.
"Test point 1-14" K = 1 o'clock, we can in the shortest path algorithm based on a more than 0/1, indicating whether the key is collected, obviously, if two times to go to the same room, and no more keys, it is meaningless, so the use of shortest-circuit algorithm can be.
"Test point 1-18" The above approach inspires us to represent the state as an integer between 1-n and a 0/1 array of length k, and then the shortest path algorithm. However, as the number of States increases, some of the shortest-circuiting algorithms may time out. Notice that the edges are not of a length, so we can use BFS to search. The total state of the BFS is O (N * 2K), each edge is accessed at most 2K times, so the complexity of the transfer is O (M * k * 2K), the total time complexity is O ((M * k + N) * 2K).
"Test point 1-20" when M, N, K are large, the above algorithm will still time out. The bottleneck of complexity is to determine whether an edge can be passed, consider a binary number instead of a 0/1 array of length K. When judging whether an edge can be passed, simply determine whether the current key and the key above it are still equal to the key needed on the edge; when walking to a new room, place the current key or the key in the room. As a result, the time complexity is optimized to O ((M + N) * 2K), which can be passed through the subject.
____________________________________________________________________________________________
Anyway, I remember when I was in the province, nothing.
Maybe it really needs a lot of discipline.
I started writing SPFA myself.
Does not consider the state of the previous cloth cannot be added directly to the now array
Always WA
When I knocked again, I suddenly woke up.
DFS backtracking avoids having to open a State again
A DFS copy SPFA version:
#include <bits/stdc++.h> #define MAXN 5001 #define MAXM 6001 using namespace std;
Template <typename t> void Read (T &x) {x=0;int F=1;char Ch=getchar (); for (;!
IsDigit (CH); Ch=getchar ()) if (ch== '-') f=-1;
for (; isdigit (ch); Ch=getchar ()) x= (x<<1) + (x<<3) +ch-' 0 ';
X*=f;
} int n,m,k;
int tot;
int HEAD[MAXN],DIS[MAXN];
BOOL VIS[MAXN];
int a[maxn][11];
int now[11];
struct node{int to,nxt;
int key[11];
}EDGE[MAXM];
void Add (int u,int v) {++tot;
Edge[tot].to=v;
Edge[tot].nxt=head[u];
Head[u]=tot; for (int i=1;i<=k;++i) read (Edge[tot].
Key[i]);
} void Dfs (int u) {vis[u]=1;
for (int i=1;i<=k;++i) now[i]+=a[u][i];
for (int e=head[u];e;e=edge[e].nxt) {bool flag=1; for (int i=1;i<=k;++i) {if (Edge[e].
Key[i]>now[i]) {flag=0;
Break
}} if (flag) {if (dis[edge[e].to]>dis[u]+1) {dis[edge[e].to]=dis[u]+1;
if (!vis[edge[e].to]) DFS (edge[e].to);
}}} vis[u]=0;
for (int i=1;i<=k;++i) now[i]-=a[u][i]; } int Main () {READ (n), read (m), read (k);
for (int i=1;i<=n;++i) {for (int j=1;j<=k;++j) read (a[i][j]);
} for (int i=1;i<=m;++i) {int u,v;
Read (U), read (v);
Add (U,V);
} fill (DIS+1,DIS+N+1,1E9);
memset (vis,0,sizeof (VIS));
dis[1]=0;
DFS (1);
if (dis[n]==1e9) cout<< "No solution" <<endl;
else cout<<dis[n]<<endl;
return 0; }
Considering that there are only 0 12 cases of keys,
Binary optimization is a common method
Reference to the STD
How the binary numbers that have been bothering for a long time
A simple shift is all that's possible.
found that the provincial style is mostly written in the main function
Direct return 0 to end operation
Much more convenient than opening bool and writing functions.
The following bfs+ binary versions:
#include <bits/stdc++.h> #define MAXN 5005 #define MAXK #define MAXQ 6000005 using namespace std;
Template <typename t> void Read (T &x) {x=0;int F=1;char Ch=getchar (); for (;!
IsDigit (CH); Ch=getchar ()) if (ch== '-') f=-1;
for (; isdigit (ch); Ch=getchar ()) x= (x<<1) + (x<<3) +ch-' 0 ';
X*=f;
} struct edge{int to,value;};
Vector<edge> A[MAXN];
int N,M,K,VALUE[MAXN];
int POS[MAXQ],CURR[MAXQ];
int ANS[MAXN][MAXK];
int main () {read (n), read (m), read (k);
if (n==1) {cout<< "0" <<endl;;
return 0;
} for (int i=1;i<=n;++i) {int cu=0;
for (int j=0;j<k;++j) {int tmp;
Read (TMP);
cu+=tmp<<j;
} VALUE[I]=CU;
} for (int i=1;i<=m;++i) {int x,y,cu=0;
Read (x), read (y);
for (int j=0;j<k;++j) {int tmp;
Read (TMP);
cu+=tmp<<j;
} a[x].push_back (Edge) {Y,CU});
} memset (ans,-1,sizeof (ans));
int l=0,r=0;
POS[0]=1,CURR[0]=VALUE[1];
ans[1][value[1]]=0;
while (l<=r) {int tmp=pos[l]; for (int i=0;i<a[tMp].size (); ++i) {if ((A[tmp][i].value&curr[l]) ==a[tmp][i].value&&ans[a[tmp][i].to][value[a[tmp][i].
To]|curr[l]]==-1) {++r;
pos[r]=a[tmp][i].to;
CURR[R]=VALUE[A[TMP][I].TO]|CURR[L];
ans[pos[r]][curr[r]]=ans[pos[l]][curr[l]]+1;
if (pos[r]==n) {cout<<ans[pos[r]][curr[r]]<<endl;
return 0;
}}} ++l;
} cout<< "No solution" <<endl;
return 0; }
Really very much thanks to XyX ... Some points from XyX:
Static memory, equivalent to open global variable
That is, even if the function is called multiple times, the value of the variable will not change.
Not clear zero.
Removing the static is equivalent to opening the array to the system stack.
And the system stack is only 8MB (default)
Because you did not deliberately adjust the system stack, so burst the stack
In regular tournaments, the system stack is typically opened to memory limits
But on the safe side, do not add static to the subroutine. Define large arrays
Again, it is emphasized that variables defined with static will not be zeroed. will not clear zero. will not clear zero. will not clear zero. will not clear zero. will not clear zero. So, if static TMP = 5 is present, then the value of TMP is not 5 when the second call is made
About variable names:
English word Remove vowel letter next---NXT
Numbers use Roman numerals X1,y1-xi,yi