Well, with the help of the poj1185 artillery layout, I learned about the state compression dynamic planning carefully.
First, with the help of the question, we can see that State compression is a Xiami thing .. OK Follow me
1. State Compression
Based on the meaning of the question, we have to place some cannons on the map with a length of M (hereinafter referred to as "Cannon", it should not be harmonious). So, first of all, we do not consider mountains, we have to find out all the placement methods, and note that only one row and the length is m (well, you may have to consider one row, left and right are separated by two, they are not in the scope of attacks. What about them? Click here first)
1. Find out all the methods for launching the gun.
Suppose the length is 7, so let's look at the method of gun release. 0 indicates not to put, 1 indicates to put one:
2. solution-compression of reference status
Once we know that the corresponding length is m and a row can be shot, we can use these cases to solve the problem. But don't worry. We know that for the length is m, there will be many states, but do we have to open a two-dimensional array of x * y to save all States? State compression is introduced here:
We know that the M of the question is <= 10, and all the gun States are represented in 01, so we can use an integer instead of an array for each State, as follows:
Then we use an array pao_st [] to store all States:
Pao_st [0] = 0 = (Binary) ...... 0000000 (here an integer has 32 bits, we only need to use the following)
Pao_st [1] = 1 = (Binary) ....... 0000001
Pao_st [2] = 2 = (Binary) ....... 0000010
Pao_st [3] = 4 = (Binary )...... 0000100 then it is obvious that there is no state of 3 here, because the binary of 3 ..... 000011, so the two guns are not in the attack scope.
............
Pao_st [CNT] = 73 = (Binary) ...... 1001001 then CNT indicates the total number of States. The last State must be 73, because this state is the largest.
So far, we have changed the space overhead of the CNT * 7 to a one-dimensional array space of the CNT -- so here is the purpose of State compression-space saving
Therefore, for the question m <= 10, a maximum of 61 placement statuses are calculated by the predecessors.
2. How to solve problems after state Compression
OK, so far, we have learned what is state compression, so we will solve the problem after state compression.
1. Don't worry. You need to understand the basic method.
Therefore, if we treat these integers as binary numbers, we must have corresponding operations:
'|','&','^','~ ','<','>'Okay, these basic things will not be described one by one.
2. See how to use it.
For the above, the length is m, and we have obtained the gun state pao_st [], then consider a line of a map, we can enumerate all the States to see if a certain state can be put on this map with mountain plains?
First, we need to perform binary processing on the map. For example, a line is temporarily called the map of line I:
Phppppp ------> we also map it to binary, get a Mountain State shan_st [I] = (Binary)... 01000000
So when we only consider whether row I can put a state of 1, we can use it in this way. If (Shan _ [I] & Pao [1]) ---->, it means we can't put it, according to the above example 0100000 & 0000001 = 0000000, the above example can be placed. For example, Shan _ [I] = 0000001, so shan_st [I] & Pao [1] = 0000001 & 0000001 = 0000001 = 1; it means putting the gun on the hill !!! No !!!!!
So here we can look at the problem that we ignored earlier: Consider whether the gun can be put up or down. Suppose the gun pao_st [J] in the J state of line I. if (pao_st [k]) (pao_st [J] & Pao [k]) ---> indicates that pao_st cannot be set... The same as above.
3. After learning about the basics, start DP
First, let's look at the state transition equation of poj1185:
DP [I] [J] [k] indicates the current row I. The status is J, and the I-1 status of the previous row is K
DP [I] [J] [k] = max (DP [I] [J] [K], DP [I-1] [k] [p] + sum [J]); sum [J] indicates the number of guns placed in the J State-that is, the number of 1 in the binary corresponding to pao_st [J ].
Directly mount the file: the comments in the Code are more detailed.
# Include <stdio. h> # include <string. h> # define Max 105int n, m; char map [Max] [Max/10]; int pao_st [61], CNT; // The status of the gun, that is, the placement method, and the number of states | based on the calculation by the predecessors, m <= 10 status up to 61, you can also try int sum [61]; // number of guns that can be placed in each State int DP [Max] [61] [61]; int shan_st [Max]; // int max (int A, int B) {return A> B? A: B;} // --------------- initialize the status of the gun, that is, the method of initial gun release ----------------- beginbool can (INT X) {// determine the state of X-that is, the binary state is not feasible if (X & (x <1) return false; If (X & (x <2 )) return false; return true;} int get_num (int x) {// The number of 1 s in the binary state of X, that is, the number of guns in this state: int num = 0; while (x) {If (X & 1) num ++; X/= 2;} return num;} void init_paost () {// For M columns, initialize the status CNT = 0; For (INT I = 0; I <(1 <m); I ++) {If (CAN (I )) {pao_st [CNT] = I; Sum [CNT ++] = get_num (I) ;}}// ----------------- initialize the status of the gun, that is, the method for initial shot ---------------- endint main () {While (~ Scanf ("% d", & N, & M) {init_paost (); // -- 1 --- initialize the status of the gun, that is, the method of the initial shot for (INT I = 0; I <n; I ++) scanf ("% s", map [I]); // -- 2 --- get map memset (shan_st, 0, sizeof (shan_st); // -- 3 --- initialize the Mountain State for (INT I = 0; I <n; I ++) {for (Int J = 0; j <m; j ++) {If (Map [I] [J] = 'H ') {shan_st [I] + = (1 <j); // here + can be changed to | same operation result }}} memset (DP, 0, sizeof (DP )); // -- 4 --- initialize the first line for (INT I = 0; I <CNT; I ++) {If (shan_st [0] & pao_st [I]) continue; // If the method of the first line conflicts with that of the I method, continue DP [0] [I] [0] = sum [I];} for (INT I = 0; I <CNT; I ++) // -- 5 --- initialize the second row {If (shan_st [1] & pao_st [I]) continue; for (Int J = 0; j <CNT; j ++) {// If the I method does not conflict with the 2nd-row Mountain, next, let's see if there is any conflict between this line and the first line. If (shan_st [0] & pao_st [J]) continue; // Of course, the first line should also be able to place the cannon if (pao_st [I] & pao_st [J]) Continue of Method J; // you must also ensure I, J is not in the attack range. DP [1] [I] [J] = max (DP [1] [I] [J], DP [0] [J] [0] + sum [I]) ;}}for (INT I = 2; I <n; I ++) {// -- 6 --- Other DP rows for (Int J = 0; j <CNT; j ++) {If (shan_st [I] & pao_st [J]) continue; for (int K = 0; k <CNT; k ++) // consider putting the K gun in the previous line {If (shan_st [I-1] & pao_st [k]) continue; if (pao_st [J] & pao_st [k]) continue; // ensure that the current line and the previous line do not interfere with each other for (INT p = 0; P <CNT; P ++) // check the above two rows {If (shan_st [I-2] & pao_st [p]) continue; If (pao_st [p] & pao_st [k]) | (pao_st [p] & pao_st [J]) continue; // The first two guns do not conflict with the following. DP [I] [J] [k] = max (DP [I] [J] [K], DP [I-1] [k] [p] + sum [J]) ;}}} int ans = 0; // obtain the maximum solution for (INT I = 0; I <CNT; I ++) {for (Int J = 0; j <CNT; j ++) {If (DP [N-1] [I] [J]> ans) ans = DP [N-1] [I] [J];} printf ("% d \ n", ANS);} return 0 ;}
Note the following points:
In the initialization operation:
Memset (shan_st, 0, sizeof (shan_st); // -- 3 --- initialize the state of the obtained map for (INT I = 0; I <N; I ++) {for (Int J = 0; j <m; j ++) {If (Map [I] [J] = 'H ') {shan_st [I] + = (1 <j); // here + can be changed to | same operation result }}}
If the mountain is like this: phpph, we can know from the code that we actually have changed its shan_st [I] to this ----> .... 10010, which is the opposite of the map, because it corresponds to 32 bits of the int, we only need the next 10 bits. <The Operation also starts from the right, when J = 2, 1 <j is... 00010. The operation is actually... 00000 |... 00010 = 00010, but this does not affect the status of all the corresponding guns, because all feasible gun statuses are symmetric.
All right, now, it's time to get it done !!!
Personal ignorance. Please correct and discuss it!
Pao_st [1] = 1 = (Binary) ...... 201710000001pao_st [1] = 1 = (Binary) ...... 0000001