将功抵过 题解
题目
作为间谍专家的Elvis Han受窃取X星球军事中心的秘密情报,他已经成功进入军事中心。但是很不幸的是,在他还没有找到任务需要情报的时候就被发现,这时他清楚他不可能完成任务了,不过还有机会将功补过,也就是得到一些不如任务情报有价值的其他情报,如果得到的情报的总价值大于等于任务情报价值,他也不会受到惩罚。很幸运的是他已经得到的军事中心的地图,情报都是隐藏在各个道路上的,但是他只有时间遍历一定数量的路(时间宝贵呀!还要逃跑。。)现在你做为他的助手,给你地图和每个道路情报价值,希望你分析出,看他能不能将功补过。
军事中心是一个严格的二叉树,也就是说,如果有个点可以分道,一定是分出,也只分出2条道路,现在Elvis Han正处在第一个分道处,也就是说树的根结点处。每条道路上都有一个分数,就是这个道路上的情报价值。但是他只有时间走M条路,他的最终情报价值总和就是他所经过的路的情报价值总和(假设他到过的路一定可以把所有情报得到)希望你给出一个方案使得他可以尽量多地获取情报以便将功补过。
输入
共有N行:
第一行:3个数据:N,M,Q(N表示有多少个路口,包括分道和不分道的路口;M表示他可以有时间走的道路总数;Q表示他的任务情报的价值)
第2~N行:每行3个数据,Xi,Yi,Wi (X,Y表示第I条道路连接的2个路口,W表示这条道路上的情报价值分, 注意,所有数据均在Lonint范围内)
输出
共包含2行:
第一行:输出TRUE/FALSE(注意大小写),表示他是否可以收集够任务情报价值
第二行:输出一个数据:
如果他可以完成任务,就输出他收集的情报总价值超过任务情报价值的部分。(正数)
如果不能完成任务,就输出一个数,表示他不能还差多少分才够任务情报价值。(负数)
样例
input 1
3 1 10
1 2 10
1 3 8
output 1
TRUE
0
input 2
9 3 49
6 2 15
7 2 10
8 7 6
7 9 15
1 3 20
2 1 10
4 3 8
3 5 7
output 2
FALSE
-4
解题思路
啊这,又是二叉苹果树
换了个故事
代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct hhx{
long long to,next;
}m[220];
long long n,m1,z,x,y,t,q,p[120],f[120][120],w[120][120],head[120];
void add(int x,int y)
{
m[++t].to=y;
m[t].next=head[x];
head[x]=t;
}
void dp(int d)
{
p[d]=1;
for (int i=head[d];i;i=m[i].next)
{
if (p[m[i].to]==1) continue;
dp(m[i].to);
for (int j=m1;j>0;j--)
for (int k=j-1;k>=0;k--)
f[d][j]=max(f[d][j],f[m[i].to][k]+f[d][j-k-1]+w[d][m[i].to]);
}
}
int main()
{
scanf("%lld%lld%lld",&n,&m1,&q);
for (int i=1;i<n;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
w[x][y]=w[y][x]=z;
add(x,y);
add(y,x);
}
dp(1);
if (f[1][m1]>=q)
cout<<"TRUE"<<endl<<f[1][m1]-q<<endl;
else cout<<"FALSE"<<endl<<f[1][m1]-q<<endl;
return 0;
}