The coordinates of n locations and the weights of each location are given, that is, n vertices in a graph. vertices have edge weights. Now the referee is at point 1. You need to assign these referees to these points. It is known that the sum of the right of each referee to the point is not greater than m, and one point cannot be accessed by two referees. Now we have two questions: 1. At least a few Referees can cover all vertices. 2. Given countless referees, how can we access these vertices to minimize the total edge and Sum? The referee must return to after the visit, in addition, the sum of the points of a referee's access cannot exceed m.
Solution: I thought about the 1004 question in the Tianjin division yesterday. I thought of algorithms during the competition, but I did not dare to think about them. I had been thinking about a secure algorithm and eventually didn't have an ac.
Later, I talked to acmer from other schools and thought about whether to try it. If not, I will search for a paper tomorrow because it is a classic mTSP problem. But I didn't expect it to be even ac. It's amazing to be ac. The complexity is O (2 ^ (2 * n) + (2 ^ n * n ^ 2 )), the ranking is still very high. The first sentence that ac thought of was not "ac", but "Nima". Does Sun Yat-sen University like this ?..
It may not be a positive solution, but I still write down my thoughts. I feel that both questions are classic.
Question 1: If the minimum number of referers is used to cover these points, the idea is to first compress the selection set of 2 ^ n locations into 2 ^ n items, the item weight is the sum of vertex weights in the set. If the sum is <= m, it is a valid combination and saved. In this way, we can obtain a valid tot combination, and carry out a 01 backpack for this tot combination. dp [I] indicates the minimum cost when the capacity is I, which is different from that of a conventional backpack, but the essence is the same. State transition equation: dp [I] = min (dp [I], dp [j] + 1) (j is the subset of I, I = j | state [k] and j and state [k] have no intersection. state [k] indicates the k valid items)
PS: Later I found that this question can be solved with greed. I can select the largest one each time until this time I cannot select one.
The second question: mTsp, a multi-Traveling Salesman Problem, is quite classic. The idea is to convert mtsp into a general tsp, and then merge each tsp into an answer. O (2 ^ n * n ^ 2) first) np [I] indicates that all locations where a referee goes through the set of I are returned to the minimum weight sum of the original vertex, then np [I] = min (np [I], np [k | (1 <0)] + np [(I-k) | (1 <0)]) (I must contain 0 nodes, because the subset may not contain 0 nodes, so it must be equal to 1 <0 or, in this way, the edge rights of the two referees are merged ).
Test data:
Input:
3 3
0 0
0 3
0 4
0
2
2
3 2
0 0
0 3
1 0
0
1
2
3 1
0 0
0 3
0 1
0
1
2
4 9
1 2
1 3
2 1
3 1
0
5
6
4
16 3500
30 40
37 52
49 49
52 64
31 62
52 33
42 41
52 41
57 58
62 42
42 57
27 68
43 67
58 48
58 27
37 69
0
19
30
16
23
11
31
15
28
8
8
7
14
6
19
11
Input:
2 14
2 8
-1-1
2 11
1 164
Code:
[Cpp]
# Include <stdio. h>
# Include <string. h>
# Include <math. h>
# Include <algorithm>
Using namespace std;
# Define MIN (1 <17)
# Deprecision MAX 110000
# Define INF (1 <29)
# Define min (a, B) (a) <(B )? (A) (B ))
Int tot, ans1, ans2, n, m; // the total number of valid items. answers to the first and second questions
Int x [20], y [20], val [20]; // right of the left side and Vertex
Int dp [MAX], state [MIN]; // used in the first question
Int map [20] [20], isok [MIN]; // Edge Weight, valid item set
Int cost [17] [MIN], np [MIN]; // used in the second question
Void Initial (){
Int I, j, k;
Tot = 0;
Memset (map, 0, sizeof (map ));
For (I = 0; I <(1 <n); ++ I)
Dp [I] = np [I] = INF;
For (I = 0; I <= n; ++ I)
For (j = 0; j <(1 <n); ++ j)
Cost [I] [j] = INF;
Cost [0] [1] = 0;
}
Int cmp1 (int a, int B ){
Return a> B;
}
Int Solve_Tanxin (){
Int I, j, k, mmin = INF;
Int tp [20], vis [20];
For (I = 0; I <n; ++ I)
Vis [I] = 0, tp [I] = val [I];
Sort (tp, tp + n, cmp1 );
For (I = 1; I <= n; ++ I ){
Int rest = m;
For (j = 0; j <n; ++ j)
If (! Vis [j] & tp [j] <= rest)
Rest-= tp [j], vis [j] = 1;
;
For (j = 0; j <n & vis [j] = 1; ++ j );
If (j = n) return I;
}
Return INF;
}
Int Solve_First (){
Int I, j, k, mmin = INF;
Dp [0] = 0;
For (I = 0; I <tot; ++ I)
For (j = (1 <n)-1; j> = 0; -- j ){
If (dp [j] = INF) continue;
Int st = j + state [I];
If (st! = (J | state [I]) continue;
Dp [st] = min (dp [st], dp [j] + 1 );
}
Return dp [(1 <n)-1];
}
Void GetDist (){
For (int I = 0; I <n; ++ I)
For (int j = I + 1; j <n; ++ j ){
Double xx = x [I]-x [j];
Double yy = y [I]-y [j];
Xx * = xx, yy * = yy;
Map [I] [j] = map [j] [I] = ceil (sqrt (xx + yy ));
}
}
Int OK (int x ){
Int sum = 0, I;
For (I = 0; I <n; ++ I)
If (x & (1 <I) sum + = val [I];
Return sum <= m;
}
Int TSP_Second (){
Int I, j, k;
GetDist ();
For (I = 1; I <(1 <n); ++ I) if (isok [I]) {
For (j = 0; j <n; ++ j) if (I & (1 <j )){
Np [I] = min (np [I], cost [j] [I] + map [j] [0]);
For (k = 0; k <n; ++ k) if (I & (1 <k) = 0)
Cost [k] [I | (1 <k)] = min (cost [k] [I | (1 <k)], cost [j] [I] + map [j] [k]);
}
}
For (I = 1; I <(1 <n); ++ I)
If (I & 1) for (j = (I-1) & I; j = (j-1) & I)
Np [I] = min (np [I], np [j | 1] + np [(I-j) | 1]);
Return np [(1 <n)-1];
}
Int main (){
Int I, j, k;
While (scanf ("% d", & n, & m )! = EOF ){
Initial ();
For (I = 0; I <n; ++ I)
Scanf ("% d", & x [I], & y [I]);
For (I = 0; I <n; ++ I)
Scanf ("% d", & val [I]);
For (I = 1; I <(1 <n); ++ I ){
Isok [I] = OK (I );
If (isok [I]) state [tot ++] = I;
}
Ans1 = Solve_Tanxin ();
// Ans1 = Solve_First ();
If (ans1 = INF)
Ans1 = ans2 =-1;
Else ans2 = TSP_Second ();
Printf ("% d \ n", ans1, ans2 );
}
}