洛谷-【动态规划1】动态规划的引入2

P2196 [NOIP 1996 提高组] 挖地雷

题目描述

在一个地图上有 N (N≤20) 个地窖,每个地窖中埋有一定数量的地雷(每个地窖的地雷均不超过 300 个)。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后每次可以移动到一个编号比当前节点大且联通的节点去挖地雷,当无满足条件的节点时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。

输入格式

有若干行。

第 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复制

复制代码
5
10 8 4 7 6
1 1 1 0
0 0 0
1 1
1

输出 #1复制

复制代码
1 3 4 5
27

说明/提示

【样例解释】

最优路径为 1→3→4→5,结果为 27。

【题目来源】

NOIP 1996 提高组第三题。

实现代码:

cpp 复制代码
#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;
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)
{
	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;
}

P1434 [SHOI2002] 滑雪

题目描述

Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:

复制代码
1   2   3   4   5
16  17  18  19  6
15  24  25  20  7
14  23  22  21  8
13  12  11  10  9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 24−17−16−1(从 24 开始,在 1 结束)。当然 25-24-23-...-3-2-1 更长。事实上,这是最长的一条。

输入格式

输入的第一行为表示区域的二维数组的行数 R 和列数 C。下面是 R 行,每行有 C 个数,代表高度(两个数字之间用 1 个空格间隔)。

输出格式

输出区域中最长滑坡的长度。

输入输出样例

输入 #1复制

复制代码
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9

输出 #1复制

复制代码
25

说明/提示

对于 100% 的数据,1≤R,C≤100。

实现代码:

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,m,a[201][201],s[201][201],ans;
bool use[201][201];
int dfs(int x,int y){
    if(s[x][y])return s[x][y];
    s[x][y]=1;
    for(int i=0;i<4;i++)
    {  int xx=dx[i]+x;
       int yy=dy[i]+y;
       if(xx>0&&yy>0&&xx<=n&&yy<=m&&a[x][y]>a[xx][yy]){
       	  dfs(xx,yy);
          s[x][y]=max(s[x][y],s[xx][yy]+1);
       }
    }
    return s[x][y];
}
int main()
{	
   scanf("%d%d",&n,&m);
   for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
       scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        ans=max(ans,dfs(i,j));
    printf("%d",ans);
    return 0;
}

P4017 最大食物链计数

题目背景

你知道食物链吗?Delia 生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条。于是她来就来求助你,然而你也不会啊!写一个程序来帮帮她吧。

题目描述

给你一个食物网,你要求出这个食物网中最大食物链的数量。

(这里的"最大食物链",指的是生物学意义上的食物链 ,即最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者。)

Delia 非常急,所以你只有 1 秒的时间。

由于这个结果可能过大,你只需要输出总数模上 80112002 的结果。

输入格式

第一行,两个正整数 n、m,表示生物种类 n 和吃与被吃的关系数 m。

接下来 m 行,每行两个正整数,表示被吃的生物 A 和吃 A 的生物 B。

输出格式

一行一个整数,为最大食物链数量模上 80112002 的结果。

输入输出样例

输入 #1复制

复制代码
5 7
1 2
1 3
2 3
3 5
2 5
4 5
3 4

输出 #1复制

复制代码
5

说明/提示

各测试点满足以下约定:

测试点编号 n m
1,2 ≤40 ≤400
3,4 ≤100 ≤2×103
5,6 ≤103 ≤6×104
7,8 ≤2×103 ≤2×105
9,10 ≤5×103 ≤5×105

对于 100% 的数据,1≤n≤5×103,1≤m≤5×105

【补充说明】

数据中不会出现环,满足生物学的要求。(感谢 @AKEE)

实现代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000001;
const int mod=80112002;
queue<int> q; 
int d[maxn],in[maxn],eat[maxn],head[maxn];
int n,m,tot,ans;
struct E{
	int to,nxt;
}e[maxn];
inline void add(int u,int v)
{
	e[++tot].to=v;
	e[tot].nxt=head[u];
	head[u]=tot;
}
inline void topo()
{
	for(int i=1;i<=n;i++)
	{
		if(in[i]==0)
		{
			q.push(i);
			d[i]++;
		}
	}
	while(!q.empty())
	{
		int p=q.front();
		q.pop();
		for(int i=head[p];i;i=e[i].nxt)
		{
			int go=e[i].to;
			d[go]=(d[go]+d[p])%mod;
			in[go]--;
			if(in[go]==0)
			q.push(go);
		}
	}
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b;
		cin>>a>>b;
		add(a,b);
		in[b]++;
		eat[a]++;
	}
	topo(); 
	for(int i=1;i<=n;i++)
	{
		if(eat[i]==0)
		ans=(ans+d[i])%mod;
	}
	cout<<ans;
}

P1115 最大子段和

题目描述

给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。

输入格式

第一行是一个整数,表示序列的长度 n。

第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 ai​。

输出格式

输出一行一个整数表示答案。

输入输出样例

输入 #1复制

复制代码
7
2 -4 3 -1 2 -4 3

输出 #1复制

复制代码
4

说明/提示

样例 1 解释

选取 [3,5] 子段 {3,−1,2},其和为 4。

数据规模与约定
  • 对于 40% 的数据,保证 n≤2×103。
  • 对于 100% 的数据,保证 1≤n≤2×105,−104≤ai≤104。

2026/01/21:增加一组 hack 数据

实现代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,a[200020],b[200020],i,ans=-2147483647;

int main(){
   cin>>n;
   for(i=1;i<=n;i++){
       cin>>a[i];
       if(i==1) b[i]=a[i];
       else b[i]=max(a[i],b[i-1]+a[i]);
       ans=max(ans,b[i]);
   }
   cout<<ans;
   return 0;
}
相关推荐
重生之我是Java开发战士1 小时前
【动态规划】背包问题:完全背包,二位费用的背包问题,似包非包
算法·动态规划
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题 第71题】【Mysql篇】第1题:索引是什么?
java·开发语言·b树·mysql·面试
LabVIEW开发2 小时前
LabVIEW实现FDTD 电磁仿真
算法·labview·labview知识·labview功能·labview程序
fpcc2 小时前
c++编程实践——历史记录的管理
c++
九皇叔叔2 小时前
VMware 安装 麒麟操作系统
java·开发语言·虚拟机·麒麟操作系统·vmware安装
Together_CZ2 小时前
DTSemNet :Vanilla Gradient Descent for Oblique Decision Trees——用于倾斜决策树的普通梯度下降
算法·决策树·机器学习·vanilla·gradient·dtsemnet·用于倾斜决策树的普通梯度
一条大祥脚2 小时前
ABC459 贪心构造|树形DP|组合数学|贪心|单调栈|势能|前缀和
算法·深度优先
weixin199701080162 小时前
[特殊字符] 人工抓取数据革命:从“人肉爬虫”到“智能数据工厂”全面转型指南
开发语言·爬虫·python
灰灰勇闯IT3 小时前
DeepEP:MoE 推理的 AllToAll 通信瓶颈怎么解
算法·cann