时间限制: 1 s
空间限制: 1000 KB
题目等级 : 黄金 Gold
查看运行结果
题目描述 Description
在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从第一个地窖开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
输入描述 Input Description
输入文件mine.in有若干行。
第1行只有一个数字,表示地窖的个数N。
第2行有N个数,分别表示每个地窖中的地雷个数。
第3行至第N+1行表示地窖之间的连接情况:
第3行有n-1个数(0或1),表示第一个地窖至第2个、第3个、…、第n个地窖有否路径连接。如第3行为1 1 0 0 0 … 0,则表示第1个地窖至第2个地窖有路径,至第3个地窖有路径,至第4个地窖、第5个、…、第n个地窖没有路径。
第4行有n-2个数,表示第二个地窖至第3个、第4个、…、第n个地窖有否路径连接。
… …
第n+1行有1个数,表示第n-1个地窖至第n个地窖有否路径连接。(为0表示没有路径,为1表示有路径)。
输出描述 Output Description
输出文件wdl.out有两行数据。
第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。
第二行只有一个数,表示能挖到的最多地雷数。
样例输入 Sample Input
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
样例输出 Sample Output
1 3 4 5
27
数据范围及提示 Data Size & Hint
(N<=20)
本题是一个经典的动态规划问题。很明显,题目规定所有路径都是单向的,所以满足无后效性原则和最优化原理。设W[i]为第i个地窖所藏有的地雷数,A[i][j]表示第i个地窖与第j个地窖之间是否有通路,F[i]为从第i个地窖开始最多可以挖出的地雷数,则有如下递归式: F[i]=max{ W[i]+ F[j]} (i<j<=n , A[i][j]=true) 边界:F[n]=W[n] 于是就可以通过递推的方法,从后F(n)往前逐个找出所有的F[i],再从中找一个最大的即为问题2的解。对于具体所走的路径(问题1),可以通过一个向后的链接来实现。
最后一个点深坑
明明答案不唯一!!!!!!!
1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 using namespace std;
5 const int MAXN=21;
6 int a[MAXN];
7 int map[MAXN][MAXN];
8 int f[MAXN];
9 int pre[MAXN+5];
10 int pd;
11 int out(int x)
12 {
13 if(pre[x]!=x)
14 out(pre[x]);
15 printf("%d ",x);
16 }
17 int main()
18 {
19 int n;
20 scanf("%d",&n);
21 for(int i=1;i<=n;i++)
22 scanf("%d",&a[i]);
23 for(int i=1;i<=n;i++)
24 f[i]=a[i];
25 pre[1]=1;
26 for(int i=1;i<=n-1;i++)
27 {
28 for(int j=i+1;j<=n;j++)
29 {
30 scanf("%d",&pd);
31 if(pd==1)map[i][j]=1;
32 else map[i][j]=0;
33 }
34 }
35 if(n==2&&map[1][2]==0)
36 {
37 printf("2\n%d",a[2]);
38 return 0;
39 }
40 for(int i=1;i<=n;i++)
41 {
42 for(int j=1;j<=n;j++)
43 {
44 if(map[i][j]==1)
45 {
46 if(f[i]+a[j]>f[j])
47 pre[j]=i;
48 f[j]=max(f[i]+a[j],f[j]);
49
50 }
51 }
52 }
53 int ans=0;
54 int where;
55 for(int i=1;i<=n;i++)
56 if(f[i]>ans)ans=f[i],where=i;
57 out(where);
58 printf("\n");
59 printf("%d",ans);
60 return 0;
61 }