NOIP1996 提高组 挖地雷

From : http://www.tsinsen.com/ViewGProblem.page?gpid=A1105
 
问题描述
  在一个地图上有N个地窖(N<=12),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。

[题目要求]
  当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,每个地窖只能经过一次,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
输入格式
  第一行一个数n。
  第二行n个数wi表示每个点的地雷数。
  随后n-1行若干个数。第i行第j个数表示i与i+j是否连通。1为连通,0为不连通。
输出格式
  K1--K2--……….K(挖地雷的顺序)
  MAX=ans (挖地雷的数量)
  如果有多种方案则输出字典序最小的方案。
样例输入
5
10 8 4 7 6
1 1 1 1
0 0 0
1 1
1
样例输出
2-1-3-4-5
MAX=35
数据规模和约定
  n<=12
 
解决方案:
      基本思想: 深度优先搜索(DFS)或者称为回溯法(Backtracking)
      下面是C语言源代码
 1 #include <stdio.h>
 2 
 3 #define M   12
 4 
 5 typedef struct vector {
 6     int len;
 7     int data[M];
 8 } Vector;          // 向量, 用来存储挖雷的顺序
 9 
10 
11 int mine[M];      // mine[i] 表示第i个地窖中的地雷数,注意:这里i从0开始
12 int mark[M];      // 标记,mark[i] 表示第i个地窖是否已被挖过
13 int adjm[M][M];   // 邻接矩阵,表示地窖之间的连通关系
14 int N;            // 地窖数
15 int cmax, max;    // 分别为当前挖到的地雷数 和 能够挖到的最大地雷数
16 Vector cvector, vector; // cmax 和 max 对应的挖雷顺序
17 
18 
19 void sweep(int n) {
20     int i, j;
21     int flag = 1; 
22     for (i = 0; i < N; i++) {
23         if (adjm[n][i] == 1 && mark[i] == 0) {
24             flag = 0;
25             mark[i] = 1;
26             cmax += mine[i];
27             cvector.data[cvector.len++] = i;
28             sweep(i);
29             cvector.len--;
30             cmax -= mine[i];
31             mark[i] = 0;
32         }
33     }
34     if (flag) { // 已挖到当前路径最大雷数
35         if (cmax > max) {
36             max = cmax;
37             vector.len = cvector.len;
38             for (j = 0; j < cvector.len; j++) {
39                 vector.data[j] = cvector.data[j];
40             }
41         }
42     }
43 }
44 
45 
46 int main() {
47     int i, j;
48     scanf("%d", &N);
49     for (i = 0; i < N; i++) {
50         scanf("%d", &mine[i]);
51         adjm[i][i] = 0;
52         mark[i] = 0;
53     }
54     for (i = 0; i < N; i++) {
55         for (j = i + 1; j < N; j++) {
56             scanf("%d", &adjm[i][j]);
57             adjm[j][i] = adjm[i][j];
58         }
59     }
60 
61     max = 0, cmax = 0;
62     for (i = 0; i < N; i++) {
63         cvector.data[0] = i;
64         cvector.len = 1;
65         cmax = mine[i];
66         mark[i] = 1;
67         sweep(i);
68         mark[i] = 0;
69     }
70 
71     printf("%d", vector.data[0] + 1);
72     for (i = 1; i < vector.len; i++) {
73         printf("-%d", vector.data[i] + 1);
74     }
75     printf("\nMAX=%d\n", max);
76 
77     return 0;
78 }

 

posted @ 2013-12-13 22:42  william-cheung  阅读(597)  评论(0编辑  收藏  举报