本人第一篇正式题解!
本题的主要思路:
①求挖地雷的最多个数。
②输出最多地雷的挖掘方法。
明确思路后代码实现
数据范围 n<=20 所以我们完全可以跑n遍DFS 求出其中的可以一次性挖的最多地雷数, 然后再跑一遍 计路DFS 把一个等于这个最多地雷数挖法记录下来输出,本题就结束了,简单易懂的双DFS。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
const int INF=2147483647;
int n,a[21];
int f[21][21],step=0;// f[i][j]用来判断i和j是否联通。 step用来记录最多的地雷数
void read(int &x)
{
x=0;int p=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') p=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
x*=p;
}// (读入优化自动忽略)
void dfs(int x,int y)// 求最多地雷数的DFS x来记录当前到达的点,y来记录地雷数目。
{
bool p=0;
for(int i=1;i<=n;i++)
{
if(f[x][i])
{
p=1;
break;
}
}// 判断n个地窖里是否有地窖与当前地窖x联通。
if(p==0)
{
step=max(y,step);
return ;
}// 没有地窖联通,已经挖到头了,判断已挖到的地雷是否为最大地雷数。
for(int i=1;i<=n;i++)
{
if(f[x][i]) dfs(i,y+a[i]);// 如果联通就挖下去。
}
}
int e1[21];// e1数组用来记录挖掘顺序。
bool p=0;
int dfs1(int x,int y,int z)// 记录挖掘顺序的DFS x,y所代表的意义同上,z来记录已经挖了几个地窖。
{
if(y==step)
{
p=1;
for(int i=0;i<z;i++)
cout<<e1[i]<<" ";
return 0;
}// 如果为最大地雷数,输出所记录的顺序然后直接跳出就好了!
for(int i=1;i<=n;i++)
{
if(f[x][i])
{
e1[z]=i;
dfs1(i,y+a[i],z+1);
}
}
}
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
read(a[i]);
}
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
int y;
read(y);
if(y) f[i][j]=1;
}
}
for(int i=1;i<=n;i++)
{
dfs(i,a[i]);
}
for(int i=1;i<=n;i++)
{
e1[0]=i;
dfs1(i,a[i],1);
if(p) break;// 已经找到最优顺序,直接Break掉!
}
cout<<endl<<step;// 换行输出最多地雷数!
return 0;
}// AC!!!