1、 圣诞树
(tree.pas/c/cpp)
【问题描述】
圣诞特别礼物挂在一棵圣诞树上,这棵树有n层,每层有一件礼物,每件礼物都有一个价值,有的礼物还有一些连接线,与下层的礼物相连。领取礼物的规则如下:任选一件礼物,它的下面如果有连接线,则可以继续取它连接的礼物,依此类推,直至取到没有连接线的礼物才结束。你如果是第一个去取,怎样才能获得最大的价值呢?请你编一个程序解决这一问题。
【输入文件】
输入文件 tree.in 的第一行只有一个数据n (n<=100),表示有n层礼物,以下有n行数据,分别表示第1-n层礼物的状态,每行至少由一个数据构成,且第一个数据表示该礼物的价值,后面的数据表示它与哪些层礼物相连,如果每行只有一个数据则说明这层礼物没有与下层礼物相连,每个数的大小均不超过10000。
【输出文件】
输出文件 tree.out 也只有一个数,表示获得的最大价值。
【输入样例】
3
12 2 3
20
30
【输出样例】
42
一开始以为必须从第一层取,所以用的单源点,wa了。
改成floyd还是过不了,原来又是忘了赋初值!!!最短路不需要管,因为是0,但是最长路必须要赋值成-oo,否则会有无效状态被使用。
读一行有点难处理,我迫不得已使用了stringstream,这个是禁用的,但是noip再怎么也不可能卡人家的输入。。。
#include <algorithm>
#include <cstdio>
#include <string>
#include <iostream>
#include <string>
#include <sstream>
using std::string;
using std::cin;
using std::max;
using std::stringstream;
long val[110];
long f[110][110];
bool map[110][110];
string line;
stringstream ss;
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
long n;
cin >> n;
for (long i=1;i<n+1;i++)
{
cin >> val[i];
getline(cin,line);
ss.clear();
ss << line;
long v = 0;
while (ss >> v)
map[i][v] = 1;
}
memset(f,~0x3f,sizeof f);
for (long i=1;i<n+1;i++)
for (long j=1;j<n+1;j++)
if (map[i][j])
f[i][j] = val[j];
for (long i=1;i<n+1;i++)
f[i][i] = 0;
for (long k=1;k<n+1;k++)
{
for (long i=1;i<n+1;i++)
{
if (i == k) continue;
for (long j=1;j<n+1;j++)
{
if (j == i || j == k) continue;
f[i][j] = max(f[i][j],f[i][k]+f[k][j]);
}
}
}
long ans = 0;
for (long i=1;i<n+1;i++)
for (long j=1;j<n+1;j++)
ans = max(ans,f[i][j]+val[i]);
printf("%ld",ans);
return 0;
}