在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。
在这个帮派里,有一名忍者被称之为Master。除了Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。
现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被派遣,你就不需要支付管理者的薪水。
你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力,其中每个忍者的领导力也是一定的。
写一个程序,给定每一个忍者i的上级Bi,薪水Ci,领导力Li,以及支付给忍者们的薪水总预算M,输出在预算内满足上述要求时顾客满意度的最大值。
第一行包含两个整数N和M,其中N表示忍者的个数,M表示薪水的总预算。
接下来N行描述忍者们的上级、薪水以及领导力。其中的第i行包含三个整数Bi , Ci , Li分别表示第i个忍者的上级,薪水以及领导力。Master满足Bi= 0,并且每一个忍者的上级的编号一定小于自己的编号 Bi < i。
输出一个数,表示在预算内顾客的满意度的最大值。
5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1
6
【样例解释】
如果我们选择编号为1的忍者作为管理者并且派遣编号为3和编号为4的忍者,薪水总和为4,没有超过总预算4。因为派遣了2个忍者并且管理者的领导力为3,用户的满意度为2 × 3 = 6,是可以得到的用户满意度的最大值。
【数据规模】
1 ≤ N ≤ 100,000 忍者的个数;
1 ≤ M ≤ 1,000,000,000 薪水总预算;
0 ≤ Bi < i 忍者的上级的编号;
1 ≤ Ci ≤ M 忍者的薪水;
1 ≤ Li ≤ 1,000,000,000 忍者的领导力。
对于30%的数据,N ≤ 3000。
解题思路:声明两个数组person和num,person用来存储忍者上级,领导力,雇佣该忍者时剩余的金钱数和该忍者为管理者时可以拥有的最多属下的数目;num用来存储忍者的序号和雇佣该忍者需花费金额。先对num数组根据雇佣每名忍者需花费金额排序,得到新的num数组根据金钱从小到大排序。然后遍历num数组,寻找每位忍者的领导,并雇佣当前忍者,扣除所需金额,并记录在person数组中。最后进行比较,选出最佳方案。思路属于暴力破解。
#include <stdio.h>
#define M 100001
#define MAX(a,b) a>b?a:b
void swap(long long *a,long long *b);
void sort(long long (*num)[2],long long begin,long long end);
int main(void)
{
long long N=0,Mon=0;
long long person[M][4]={0},i=0,j=0,num[M][2]={0};
int father=0,money=0;
scanf("%lld %lld",&N,&Mon);
//接收数据
for(i=1;i<=N;i++)
{
num[i][0] = i;
scanf("%lld %lld %lld",*(person+i)+0,*(num+i)+1,*(person+i)+1);
person[i][2] = Mon;
}
//排序
sort(num,1,N);
//遍历num数组中的成员,寻找每位忍者的最终上司,并记录过程
for(i=1;i<=N;i++)
{
father = num[i][0];
money = num[i][1];
//寻找上司,并记录下过程中雇佣人员的增加,金额的变化
while(father!=0&&person[father][2]>=money){
person[father][2]-=money;
person[father][3]++;
father = person[father][0];
}
}
//遍历person数组,比较出最大的满意度
long long ans=0;
for(i=1;i<=N;i++)
{
ans = MAX(ans,person[i][1]*person[i][3]);
}
printf("%lld\n",ans);
return 0;
}
//交换num数组中的两个元素
void swap(long long *a,long long *b)
{
long long tmp = a[0];
a[0] = b[0];
b[0] = tmp;
tmp = a[1];
a[1] = b[1];
b[1] = tmp;
}
//对num数组排序
void sort(long long (*num)[2],long long begin,long long end)
{
long long i=0,j=0;
if(begin<end)
{
i = begin+1;
j = end;
while(i<j)
{
if(num[begin][1]<num[i][1])
{
swap(*(num+i),*(num+j));
j--;
}
else i++;
}
if(num[begin][1]<=num[i][1]) i--;
swap(*(num+begin),*(num+i));
sort(num,begin,i);
sort(num,j,end);
}
}