动态规划——挖地雷

动态规划——挖地雷

来自洛谷 P2196 [NOIP1996 提高组] 挖地雷

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bdPbbTYQ-1648368295254)(C:\Users\86180\AppData\Roaming\Typora\typora-user-images\image-20220327154830199.png)]

解题思路


由题目很容易想到的是通过动态规划来算出和某个点连接的所有点中的最大值再加上该点本身的值,但是对于整个遍历的方式,自己出现了错误。其实最简单的方式应当是类似于Floyd算法,对于每个点,都需要查找遍历其他的所有点,来找到对于每个点来说与其相连的最大值,并且记录下与其相连的点,最后再递归调用打印出挖的顺序。另外该题需要只记录 e i j e_{ij} eij其中( i < j i<j i<j),不然的话会出现重复的情况

模拟过程


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TB737Vdk-1648368295255)(C:\Users\86180\AppData\Roaming\Typora\typora-user-images\image-20220327155605633.png)]

对于题目中给出的输入,做出模拟的过程:

当i=0时,与其相连的有1,2,3个点,找到最大的点,但其实这个时候所有点都还没有被赋值,所以最后只能得到res[0]=10

当i=1时,与其相连的点只有0,所以res[1]=res[0]+8=18 p[1]=0

当i=2时,与其相连的点只有0,其中3大于他所以暂且用不上,所以res[2]=res[0]+4=14 p[2]=0

当i=3时,与其相连的点有0,2,其中res[2]=14>res[0] ,故res[3]=res[2]+7=21 p[3]=2

当i=4时,与其相连的点有2,3, 其中 res[3]=res[2]+6=27 p[4]=3

综上我们可以看出 我们打印出的顺序一定是顺序的 并且每次相当于是向已有的点集中加点

代码实现

#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,n) for(int i=s;i<n;i++)
const int SIZE = 100;
int nums[SIZE];
int adjm[SIZE][SIZE];

int res[SIZE];
int p[SIZE];
int max_value = 0;
int max_index = 0;
void print(int x)
{
	if (p[x] == -1)
	{
		printf("%d ", x + 1);
		return;
	}
	print(p[x]);
	if(x!=max_index)
	printf("%d ",x+1);
	else
	printf("%d", x + 1);




}



int main()
{
	memset(res, 0, sizeof(res));
	memset(adjm, 0, sizeof(adjm));
	memset(p, -1, sizeof(p));
	int n;
	scanf("%d", &n);
	rep(i, 0, n)
	{
		scanf("%d", &nums[i]);
	}



	rep(i,0,n-1)
		rep(j, i + 1, n)
	{
		int temp;
		scanf("%d", &temp);
		if (temp == 1)
		{
			adjm[i][j] = 1;//右边
		}
	}

	rep(i, 0, n)
	{
		rep(j, 0, n)

		{
			if (adjm[j][i] == 1 && res[j] > res[i])
			{
				res[i] = res[j];
				p[i] = j;
			}
		}
		res[i] += nums[i];
		if (res[i] > max_value)
		{
			max_value = res[i];
			max_index = i;
		}

	}
	print(max_index);


	printf("\n%d", max_value);
	return 0;



}

注意

洛谷的变量名似乎不能取为index,否则会编译报错

另外在cmp中,如果是>则代表升序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值