P2196 挖地雷

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

输入格式
有若干行。

第11行只有一个数字,表示地窖的个数NN。

第22行有NN个数,分别表示每个地窖中的地雷个数。

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

第33行有n-1n−1个数(00或11),表示第一个地窖至第22个、第33个、…、第nn个地窖有否路径连接。如第33行为1 1 0 0 0 … 011000…0,则表示第11个地窖至第22个地窖有路径,至第33个地窖有路径,至第44个地窖、第55个、…、第nn个地窖没有路径。

第44行有n-2n−2个数,表示第二个地窖至第33个、第44个、…、第nn个地窖有否路径连接。

… …

第n+1n+1行有11个数,表示第n-1n−1个地窖至第nn个地窖有否路径连接。(为00表示没有路径,为11表示有路径)。

输出格式
有两行

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

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

输入输出样例
输入 #1复制
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1
输出 #1复制
1 3 4 5
27

用dp+记忆化搜索来写,首先我们定义一个f(i),表示从第i个位置到第n个位置能挖到地雷的最大值,当i后面的地窖有通道时,f(i)=max(f(i),f(i+k)+m[i]),f(i+k)为下一个通道的位置,m[i]为本身地窖的地雷数,当i后面没有地窖时,f(i)=m[i];

`#include<bits/stdc++.h>
int n,a[21][21],dp[21],m[21]; //m存放地雷数,a存放地窖通道的关系,定义在using namespace std前
using namespace std;
int dfs(int k);
bool check(int n) //判断dp[n]之前是否已经有值了,记忆化搜索
{
if(dp[n]!=0)
return true;
else
return false;
}
int main()
{
scanf("%d",&n);
int x=n;
for(int i=1;i<=n;i++)
scanf("%d",&m[i]);
for(int i=1;i<=n-1;i++)
{
x--;
for(int j=1;j<=x;j++)
{
scanf("%d",&a[i][j]);
}
}
int ans=0;
dp[n]=m[n];
for(int i=n-1;i>=1;i--)
{
dfs(i);
}
int index;
for(int i=1;i<=n;i++){
if(dp[i]>ans)
ans=dp[i],index=i; //求哪个通道开始挖能挖到最大的地雷数
}
printf("%d",index);
for(int i=index+1;i<=n;i++){
if(dp[index]dp[i]+m[index]){ //如果第i个挖过了,dp[i]+m[index]=dp[index];
printf(" %d",i);
index=i;
}
}
printf(" %d ",ans);
}
int dfs(int k)
{
if(check(k)) return dp[k];
int flag=0; //判断后面是否有通道
for(int i=1;i<=n-k;i++)
{
if(a[k][i]
1){
dp[k]=max(dp[k],dfs(k+i)+m[k]);
flag=1;
}
}
if(flag==0)
dp[k]=m[k];
return dp[k];
}

`

原文地址:https://www.cnblogs.com/zh1014/p/13426833.html