P2196 挖地雷(DP经典题型)NOIp1996提高组第三题

题目传送门,走你~~~

分析:经典的DP题。本题需要在道路畅通的地窖中,尽可能的挖的多的雷。即本地窖中的雷加上你后续可以去到的地窖中挖到的雷的总和。因而状态转移方程:sum[i] = max(sum[i],sum[j]+a[i])          

//a[i]本地窖中雷。j>i;sum[i]上一个地窖中。sum[j]+a[i]去到下一地窖挖到雷的总和

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 330;
/*	
	1.用a数组存储每个地窖中地雷的个数。
	2.用f数组记录路径
	3.tt数组记录是否可以有通过去下一个地窖的路径。
	4.sum数组记录和的值
*/

int a[maxn],f[maxn],tt[maxn][maxn],sum[maxn];
int main()
{
	int n;
	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 >> tt[i][j];//输入连接路径
		}
	}
	memset(sum, 0, sizeof(sum));
	memset(f, -1, sizeof(f));
	for (int i = n; i >= 1; i--)
	{
		sum[i] = a[i];
		for (int j = i+1; j <= n; j++)
		{
			if (tt[i][j] && sum[j] + a[i] > sum[i])
			{   //路径畅通,递推看一下第i行的那个元素更大,取更大的值。
				sum[i] = sum[j] + a[i];
				f[i] = j;
			}
		}
	}
	int k = 0;
	for (int i = 0; i <= n; i++)
	{//找出最大的值并记录其开始的路径。
		if (sum[i] > sum[k])
		{
			k = i;
		}
	}
	int maxx = sum[k];
	cout << k;
	k = f[k]; 
	while (k != -1)
	{
		cout << " " << k;
		k = f[k];
	}
	cout << endl;
	cout << maxx << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/fighting_yifeng/article/details/81536554