题目描述

在一个地图上有N个地窖(N20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。

输入格式

有若干行。

1行只有一个数字,表示地窖的个数N

2行有N个数,分别表示每个地窖中的地雷个数。

3行至第N+1行表示地窖之间的连接情况:

3行有n1个数(0或1),表示第一个地窖至第2个、第3个、…、第n个地窖有否路径连接。如第3行为1 1 0 0 0 … 0,则表示第1个地窖至第2个地窖有路径,至第3个地窖有路径,至第4个地窖、第5个、…、第n个地窖没有路径。

4行有n2个数,表示第二个地窖至第3个、第4个、…、第n个地窖有否路径连接。

… …

n+1行有1个数,表示第n1个地窖至第n个地窖有否路径连接。(为0表示没有路径,为1表示有路径)。

输出格式

有两行

第一行表示挖得最多地雷时的挖地雷的顺序,各地窖序号间以一个空格分隔,不得有多余的空格。

第二行只有一个数,表示能挖到的最多地雷数。

输入输出样例

输入 #1
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
输出 #1
1 3 4 5
27



由于数据很小,我又不太会dp,可以直接暴搜。顺便巩固一下dfs和回溯的写法。我没有进行任何剪枝。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int ans[25],temp[25],tot,maxmine,l,ll;
//ans记录最终答案路径,temp记录每次搜索路径,tot记录每次搜索的地雷数
//maxmine记录最终答案地雷数量,l记录每次搜索经过的房间数量,ll记录最终答案房间数量 
bool map[25][25];//记录 i,j 之间有无通路 
int a,n[25];

void refresh()
{
    ll=l;
    maxmine=tot;
    for(int i=0;i<ll;i++) ans[i]=temp[i];
    return ;
}
int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
void dfs(int x,int st)
{
    if(tot>maxmine) refresh();
    for(int i=st;i<=a;i++)
        if(map[x][i]==1)
        {
            tot+=n[i];
            temp[l++]=i;
            dfs(i,i+1);
            l--;
            tot-=n[i];
        }
}
int main()
{
    a=read();
    for(int i=1;i<=a;i++) n[i]=read();
    memset(map,0,sizeof(map));
    for(int i=1;i<a;i++)
        for(int j=i+1;j<=a;j++)
            map[i][j]=read();
    for(int i=1;i<=a;i++)
    {
        tot+=n[i];
        temp[l++]=i;
        dfs(i,i+1);
        tot-=n[i];
        l--;
    }
    for(int i=0;i<ll;i++)
    {
        if(i) printf(" ");
        printf("%d",ans[i]);
    }
    printf("\n%d",maxmine);
    return 0;
}
暴搜