备战Noip2018模拟赛5(B组)T2 Tree 采果子

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/MOMING_V/article/details/82940548

10月4日备战Noip2018模拟赛5(B组)

T2 Tree采果子

题目描述

 LYL大牛今天心情不错,于是走到埃及郊外旅游。他边走边向四周望望,发现周围有许多果树。这些树之间互相到达的时间LYL是知道的(假定每两棵树之间都拥有独立的边可以到达)。他数出了这些果树上果子的个数,并且估了估每个的价格(真是个奇怪的人).Lyl规定了一种采摘方案,就是对于第我棵树来说,它有一个[I]个果子,且所有果子价值为S [I]中,摘取时间为C [1](小时)。并且,当他摘了第我个树上的果子后,后面他所选择去摘的果树上的果子数必须大于第我棵树上的果子数目,说白了就是一个上升序列;并且每到一棵树,他都必须摘下该树上的所有果子一开始,LYL可以在任意一棵树,他只有米小时,那么,在他所拥有的限定时间内,他想知道,这样摘取的最大价值是多少?

输入格式

文件输入侧tree.in第一行2个数为:n(表示这条路上的大树数),M(总共时间)

    接下来第n + 1行,每行三个数a [i],s [i],c [i](第i + 1行输入的为第i颗果树的信息)

    且保证有1 <= A [1] <= 2 ^ 31-1; 1 <= S [1] + S [2] + ... + S [N] <= 2 ^ 31-1; S [I]> = 0; 1 <= C [1] <= 100

    接下来的Ñ行,每行Ñ个数,第I行第Ĵ个数表示从树我到树Ĵ的时间(0 <= T [I,J] <= 100)。

输出格式

输出文件tree.out有且仅有一个数,即按这样方法摘取的最大价值。

输入样例

4 10
1 10 2
2 5 3
3 6 1
4 9 4
0 1 2 3
1 0 3 4
2 3 0 5
3 4 5 0

输出样例

21

样例解释

先摘第1棵树上的,再摘第2棵树上的,然后第3棵树上的

数据范围

 对于60%的数据,1 <= N <= 60,1 <= m <= 100;

对于100%的数据,1 <= N <= 100,1 <= m <= 1000。

其实考模拟赛的时候,题面改了一下,因为太皮了,所以贴了原题

看到了美味程度(价值),采摘时间(重量),很容易看出这道题其实就是01背包,但是与传统的01背包不同的是,

  1. 因为两棵苹果树之前有距离,需要耗费时间来走,那么多加一层循环来找前面采摘的苹果就可以了,f [i] [j]表示在ih,第i棵苹果树所采摘苹果的最大美味程度
  2. 因为每次采摘的苹果要比上一次多,所以可以先排序一遍,但是要注意此时的苹果树的编号改变了,那么和邻接矩阵的对应也改变了,所以在结构中加一个没来储存苹果树原来的编号

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 101;
const int M = 1005;

struct Node{
	int apple;
	int delicious;
	int pick;
	int no;             //记录苹果树的编号
}a[N];

int n, m, i, j, r, app, del, pic, Max;
int f[M][N], adj[N][N];

bool cmp (Node a, Node b)
{
	return a.apple < b.apple;
}

int main ()
{
	freopen ("tree.in", "r", stdin);
	freopen ("tree.out", "w", stdout);
	
	scanf ("%d %d", & n, & m);
	for (i = 1; i <= n; i ++){
		scanf ("%d %d %d", & app, & del, & pic);
		a[i].apple = app;
		a[i].delicious = del;
		a[i].pick = pic;
		a[i].no = i;
	}
	for (i = 1; i <= n; i ++){
		for (j = 1; j <= n; j ++){
			scanf ("%d", & adj[i][j]);            
		}
	}
	
	sort (a + 1, a + 1 + n, cmp);            //按苹果数排序
	
	for (i = 1; i <= n; i  ++){
		f[a[i].pick][i] = a[i].delicious;            //每棵树耗费自己的采摘时间可以得到的美味值
	}
	
	for (i = 1; i <= n; i ++){
		for (j = 1; j <= m; j ++){
			f[j][i] = max (f[j][i], f[j - 1][i]);
			for (r = 1; r < i; r ++){            //和传统01背包不同的地方,找上一棵树
				if (j - adj[a[r].no][a[i].no] - a[i].pick >= 0 
					&& a[i].apple != a[r].apple){
						f[j][i] = max (f[j][i], f[j - adj[a[r].no][a[i].no] - a[i].pick][r] + a[i].delicious);
					}
			}
		}
	}
	
	Max = 0;
	for (i = 1; i <= n; i ++){
		Max = max (Max, f[m][i]);            //不确定到第几棵树的最大,从第一颗树开始找一遍
	}
	
	printf ("%d", Max);	
	
	fclose (stdin);
	fclose (stdout);
	return 0;
}

 

展开阅读全文

没有更多推荐了,返回首页