天天看点

洛古P2196 题解 兼本人第一篇题解

本人第一篇正式题解!

本题的主要思路:

①求挖地雷的最多个数。

②输出最多地雷的挖掘方法。

明确思路后代码实现

数据范围 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!!!