做慈善

题目描述

1502.做慈善 (20分) 
C时间限制:3000 毫秒 |  C内存限制:3000 Kb
题目内容:
捐款站有个点名机,每个时刻会报一个数,下一刻的报数相对于上一刻可能是加1, 或者减1,或者保持不变。点名机从0开始报数,限制在[0,100]之间。
N位富商带着钱去捐款,如果某人到达捐款站时,捐款站的点名机刚好报出他的身份号码,则他会捐出他带的财富,否则他不捐款。
请你安排一个点名机的报数,使得捐款站收到最多捐款。
 输入描述
第一行是整数N,1<=N<=100 ,
以下N行分别是每个富商的到达时间t[i],带的钱P[i],以及身份号码S[i], 满足0<=t[i]<=30000,0<=P[i]<=300,1<=S[i]<=K
 输出描述
捐款站收到的钱的最大总数
 输入样例
4
10 10 10
16 11 7
8 15 1
16 1 8
输出样例
26

解题思路:

先用sort对时间排序0~n-1,然后用dp[i]表示在满足第i个人能捐款的情况下的最大收益,其递推公式为dp[i]=第i个人所带的金额+max(dp[0:i-1]),max(dp[0:i-1])表示在第0~i-1个人中选择一个其对应dp收益最大的,让第i个人跟在其后。并且保证i能更在其身后,即满足二者时间之差大于等于二者身份号码之差的绝对值。

样例解释

排序前

10 10 10
16 11 7
8 15 1
16 1 8

排序后 
8 15 1
10 10 10
16 11 7
16 1 8

timec,numc表示时间差,和身份号码差

当i=0时,里层for跳过, 
                                   time:8,num:1,dp[0]=tmp:0+money:15=15,res=15
 当i=1时,check(a[1],a[0:0])timec:2 numc:9,不满足,即第0个和第1个排斥, 
                 time:10,num:10,dp[1]=tmp:0+money:10=10,res=15
 当i=2时,check(a[2],a[0:1])timec:8 numc:6,满足,可以跟在0的后面 ,dp[0]=15
                                            timec:6 numc:3,满足,也可以跟在1的后面 ,dp[1]=10
                 time:16,num:7,dp[2]=tmp:15+money:11=26,res=26,选择跟在收益最大的后面 
  当i=3时,check(a[3],a[0:2])timec:8 numc:7,满足,可以跟在0后面 
                                             timec:6 numc:2,满足,也可以跟在1后面 
                                             timec:0 numc:1,不满足
                  time:16,num:8,dp[3]=tmp:15+money:1=16,res=26

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
struct node{
 	int money;
	int num;
	int time;
}a[1001];
bool cmp(node x,node y){
	return x.time < y.time;
}
bool check(node x,node y){
	return x.time - y.time >= abs(x.num - y.num) ? 1 : 0;
}
int dp[1001] = {0};

int main(){

	int n,res = 0;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> a[i].time >> a[i].money >> a[i].num;
	}
	sort(a,a+n,cmp);
	//输出排序结果测试 
    cout<<endl;
	for(int i=0;i<n;i++)cout<<a[i].time<<" "<<a[i].money<<" "<<a[i].num<<endl;cout<<endl;

	for(int i = 0; i < n; i++){
		int tmp = 0;
		for(int j = 0; j < i; j++)
			if(check(a[i],a[j]) && tmp < dp[j])//a[j]可以在a[i]后面 
				tmp = dp[j];//存最大收益		
		
		if(a[i].time>=a[i].num)dp[i] = tmp +a[i].money;
		if(res <dp[i]) res=dp[i];
	}
	cout << res << endl;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值