[NOIP1996 提高组] 挖地雷(原题)

题目描述

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

输入格式

有若干行。

第\(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\)表示有路径)。

输出格式

有两行

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

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

样例 #1

样例输入 #1

5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1

样例输出 #1

1 3 4 5
27

例题分析

思路一:动态规划

不难发现要想从j到i有两个条件:

  • 两个地窖间有路相互连通(题目似乎并不允许自己挖一条……)
  • i的地雷数与目前j的总地雷数之和大于i的最大地雷数,即目前j点的最大价值与i点的价值这和大于i点的最大价值(要不然你走了干嘛……)

所以状态转移方程很简单:dp[i]=max(dp[i],dp[j]+a[i])

随后是稍微不一样的地方:它要求输出路径

如果用搜索,路径很好保存。但如果是动规的话还需要再维护一个数组pre作为每一个点的前驱(就是你从哪来的)。

比如从a到b,它符合上述两个条件,那么可以更新b点的最大价值,并且将b的前驱设为a点,那么输出时只要倒序输出即可。

AC代码如下:

点击查看代码
#include<bits/stdc++.h>
using namespace std;
bool flag[500][500]; //两个点是否连通
int a[500],dp[500],pre[500],pos,n,ans; //a为总价值,pre为前驱,dp为一维动规数组
void dfs(int num){ //输出用的函数
if(pre[num]) dfs(pre[num]);
printf("%d ",num);
return ;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
cin>>flag[i][j];
}
}
dp[1]=a[1]; //初始价值
for(int i=2;i<=n;i++){
dp[i]=a[i];
for(int j=i-1;j>0;j--){
if(flag[j][i]&&dp[i]-a[i]<dp[j]){
//不用状态转移方程是因为此处要记录前驱点
dp[i]=dp[j]+a[i];
pre[i]=j;
}
}
if(ans<dp[i]){
ans=dp[i];
pos=i;
}
}
dfs(pos);
printf("\n%d",ans);
return 0;
}

思路二:dfs暴搜

暴力骗分,但对于较强数据建议dp,或者做例如记忆化之类的优化

可以参考灰名红名大佬的第一篇题解

AC代码如下:

点击查看代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
bool f[21][21];//记录是否有路径相连
int a[21];//记录地雷数
int path[21],ans[21],cnt;//path记录路径,ans记录答案,cnt记录走了多少个点
bool b[21];//记录该点是否走过
int n;
int maxx;//记录挖的最大地雷数
bool chck(int x)//检查是否还能继续往下挖
{
for(int i=1;i<=n;i++)
{
if(f[x][i]&&!b[i]) return false;
}
return true;
}
void dfs(int x,int stp,int sum)//x记录现在位置,stp记录走了几个点,sum记录挖的地雷数
{
if(chck(x))
{
if(maxx<sum)//更新最大值和路径
{
maxx=sum;
cnt=stp;
for(int i=1;i<=stp;i++)
ans[i]=path[i];
}
return ;
}
for(int i=1;i<=n;i++)//寻找下一个能去的地方
{
if(f[x][i]&&!b[i])
{
b[i]=1;//标记走过
path[stp+1]=i;//记录路径
dfs(i,stp+1,sum+a[i]);
b[i]=0;//回溯
} }
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<n;i++)
for(int j=i+1;j<=n;j++)
{
cin>>f[i][j];//这里是单向边,题目没啥清楚,导致我调了半个小时;
}
for(int i=1;i<=n;i++)
{
b[i]=1;
path[1]=i;//记录起点
dfs(i,1,a[i]);
b[i]=0;
}
for(int i=1;i<=cnt;i++)
cout<<ans[i]<<' ';
cout<<endl<<maxx;
return 0;
}

洛谷P2196例题分析的更多相关文章

  1. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  2. 洛谷——P1165 日志分析

    P1165 日志分析 题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志.该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次 ...

  3. 洛谷 P1165 日志分析

    题目描述 M 海运公司最近要对旗下仓库的货物进出情况进行统计.目前他们所拥有的唯一记录就是一个记录集装箱进出情况的日志.该日志记录了两类操作:第一类操作为集装箱入库操作,以及该次入库的集装箱重量:第二 ...

  4. 洛谷P2196 挖地雷 [2017年4月计划 动态规划13]

    P2196 挖地雷 题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之 ...

  5. 洛谷 p2196 挖地雷 题解

    好久没有写博客了,今天水几篇博客 传送门 挖地雷这个题之前在  信息学奥赛一本通  上做过几乎一样的题,但是由于数据太水导致我当时过了,进而导致我昨天(4.28)考试丢了20分,今天写一篇题解 这个挖 ...

  6. 洛谷P2196 挖地雷(dp)

    题意 题目链接 Sol 早年NOIP的题锅好多啊.. 这题连有向边还是无向边都没说(害的我wa了一遍) 直接\(f[i]\)表示到第\(i\)个点的贡献 转移的时候枚举从哪个点转移而来 然后我就用一个 ...

  7. 洛谷——P2196 挖地雷

    题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径.当地窖及其连接的数据给出之后,某人可以从任一处 ...

  8. 洛谷—— P2196 挖地雷

    https://www.luogu.org/problem/show?pid=2196 题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定 ...

  9. 洛谷P2196 && caioj 1415 动态规划6:挖地雷

    没看出来动规怎么做,看到n <= 20,直接一波暴搜,过了. #include<cstdio> #include<cstring> #include<algorit ...

  10. 洛谷 P2196 挖地雷 & [NOIP1996提高组](搜索,记录路径)

    传送门 解题思路 就是暴力!!! 没什么好说的,总之,就是枚举每一个起点,然后暴力算一遍以这个点为起点的所有路径,在算的过程中,只要比目前找到的答案更优,就有可能是最后的答案,于是就把路径更新一遍,保 ...

随机推荐

  1. POJ3237 Tree (树链剖分)

    通过打懒标记实现区间取反,和线段树基本操作都差不多. 本题还是一道边权化为点权的问题. 200行巨长代码: 1 #include<cstdio> 2 #include<cstring ...

  2. MSQL-->存储引擎

    概述 MySQL体系结构图 Innodb引擎是在mysql的5.5版本之后的默认存储引擎. Index是在引擎层次的,不同的存储引擎index的用法不同. 存储引擎就是存储数据,建立索引,更新查询数据 ...

  3. 微软出品自动化神器【Playwright+Java】系列(五) 之 常见点击事件操作

    写在前面 明天就是周五了,这周有那么一两天心情特别不好,真的是做什么都没兴致,所以导致整个人都很丧,什么都不想做. 本打算周一就更新这篇文章的,但由于公司一直加班,每天到家很晚,都是挤时间去学,理解后 ...

  4. 认识 Redis client-output-buffer-limit 参数与源码分析

    概述 Redis 的 client-output-buffer-limit 可以用来强制断开无法足够快从 redis 服务器端读取数据的客户端.保护机制规则如下: [hard limit] 大小限制, ...

  5. .NET Core C#系列之XiaoFeng.Data.IQueryableX ORM框架

    ​ 当前对象操作数据库写法和EF Core极度类似,因为现在大部分程序员都懒得去写SQL,再一个就是项目作大了或其它原因要改数据库,每次改数据库,那么写的SQL语句大部分要作调整,相当麻烦,并且写SQ ...

  6. SQL中事务以及全局变量的使用

    事务的定义 简单的说,事务处理可以用来维护数据库的完整性,保证一批SQL语句要么全执行,要么全部不执行 事务的特性 原子性  一致性  持久性  隔离性        注:一元九个 事务的使用 sel ...

  7. 【FAQ】关于华为地图服务定位存在偏差的原因及解决办法

    一. 问题描述: 华为地图服务"我的位置"能力,在中国大陆地区,向用户展示他们在地图上的当前位置与用户的实际位置存在较大的偏差. 具体差别可以查看下方的图片: 二. 偏差较大的原因 ...

  8. Windows下pip换成清华源

    1.在C:\Users\用户名\ 下创建 pip 文件夹2.在文件夹内创建pip.ini 文件, 添加如下内容: [global] timeout = 6000 index-url = https:/ ...

  9. @RequestBody 注解问题

    /**         * 不管你是get 请求 还是 post 请求  只要你的参数名称叫做abc          * 这里的abc 必须和 postman里面的key 一样          * ...

  10. Python基础之模块:7、项目开发流程和项目需求分析及软件开发目录

    一.项目开发流程 1.项目需求分析 明确项目具体功能: 明确到底要写什么东西,实现什么功能,在这个阶段的具体要询问项目经理和客户的需求 参与人员: 产品经理.架构师.开发经理 技术人员主要职责: 引导 ...