The Ghost Blows Light
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3240 Accepted Submission(s): 1000
Problem Description
My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consists of N rooms (numbered from 1 to N) which are connected by some roads (pass each road should cost some time). There is exactly one route between any two rooms, and each room contains some treasures. Now I am located at the 1st room and the exit is located at the Nth room.
Suddenly, alert occurred! The tomb will topple down in T minutes, and I should reach exit room in T minutes. Human beings die in pursuit of wealth, and birds die in pursuit of food! Although it is life-threatening time, I also want to get treasure out as much as possible. Now I wonder the maximum number of treasures I can take out in T minutes.
Input
There are multiple test cases.
The first line contains two integer N and T. (1 <= n <= 100, 0 <= T <= 500)
Each of the next N - 1 lines contains three integers a, b, and t indicating there is a road between a and b which costs t minutes. (1<=a<=n, 1<=b<=n, a!=b, 0 <= t <= 100)
The last line contains N integers, which Ai indicating the number of treasure in the ith room. (0 <= Ai <= 100)
The first line contains two integer N and T. (1 <= n <= 100, 0 <= T <= 500)
Each of the next N - 1 lines contains three integers a, b, and t indicating there is a road between a and b which costs t minutes. (1<=a<=n, 1<=b<=n, a!=b, 0 <= t <= 100)
The last line contains N integers, which Ai indicating the number of treasure in the ith room. (0 <= Ai <= 100)
Output
For each test case, output an integer indicating the maximum number of treasures I can take out in T minutes; if I cannot get out of the tomb, please output "Human beings die in pursuit of wealth, and birds die in pursuit of food!".
Sample Input
5 10 1 2 2 2 3 2 2 5 3 3 4 3 1 2 3 4 5
Sample Output
11
Source
Recommend
liuyiding
题意:
有n个房间构成一棵树结构,n-1条路都有权值,代表经过花费的时间,一个人在房间1,出口在房间n,T秒后这座房子将要倒塌。每个房间有一定价值的宝物,问逃出时最大可带走多少价值的宝物。如果无法逃出特别输出。
(超过T秒没有到达房间n算作未逃出)
之前有个想法:dp[x][v][0] dp[x][v][1]表示从x出发经过k步回到x点的最大收益和不回到x点的最大收益。
按理来说这种做法是可行的,结果这样不断T。
解法:先找到1到n的必经之路,这些边只会走一次,而其它边会走两次。
如果这些边的权值和sumW>T,证明无法逃出,continue。
否则,用T减去权值和sumW,并将这些边的权值赋为0。
之后进行树形背包,这样可以保证走过这些必经之边。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define all(x) (x).begin(), (x).end()
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)
#define mes(a,x,s) memset(a,x,(s)*sizeof a[0])
#define mem(a,x) memset(a,x,sizeof a)
typedef long long ll;
typedef pair<int, int> pii;
const int INF =0x3f3f3f3f;
const int maxn= 100 ;
const int maxT= 500 ;
int n,nedge,T,a[maxn+10];
int fir[maxn+10],nex[2*maxn+10],to[2*maxn+10],W[2*maxn+10];
int dp[maxn+5][maxT+5];
inline void add_edge(int x,int y,int w)
{
to[nedge]=y;
W[nedge]=w;
nex[nedge]=fir[x];
fir[x]=nedge++;
}
void update(int &x,int val)
{
if(val>x) x=val;
}
void dfs(int x,int fa)
{
for0(v,T+1)
{
dp[x][v]=a[x];
}
for(int i=fir[x];~i;i=nex[i])
{
int y=to[i];if(y==fa) continue;
int w=W[i];
dfs(y,x);
for(int v=T;v>=2*w;v--)
{
int ret=dp[x][v];
for(int v2=0;v2+2*w<=v;v2++)
{
update(ret,dp[y][v2]+dp[x][v-v2-2*w]);
}
dp[x][v]=ret;
}
}
}
int time;
bool pre(int x,int fa)
{
if(x==n)
{
return true;
}
bool ok=false;
for(int i=fir[x];~i ;i=nex[i])
{
int y=to[i];if(y==fa) continue;
int & w=W[i];
if(pre(y,x))
{
ok=true;
time+=w;
w=0;
}
}
return ok;
}
int main()
{
std::ios::sync_with_stdio(false);
while(cin>>n>>T)
{
int x,y,w;
nedge=0;
mes(fir,-1,(n+1));
for1(i,n-1)
{
cin>>x>>y>>w;
add_edge(x,y,w);
add_edge(y,x,w);
}
for1(i,n) cin>>a[i];
time=0;
pre(1,-1);
if(time>T) {puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");continue;}
T-=time;
dfs(1,-1);
printf("%d\n",dp[1][T]);
}
return 0;
}
/*
2 5
1 2 5
1 2
ans=3
2 4
1 2 5
1 2
ans =no
1 5
5
ans=5
*/