【树形dp入门】UVA-12186 + HDU - 1520(白白wa掉的同学看过来!!)

看着很玄幻,其实也就是dfs+dp。

然后满足那么一个关系,在一个树上,有上级下级树形关系

uva12186是紫书上的题目。

需要注意题目:每层只要它的直接下属来就好了,不用考虑到所有底层员工,按照书上给的式子,c=(k*T-1)/100+1

每次这样来就可以了

之后贪心选取花费最少的。

写的时候遇到一点小问题:

if(d[dd]==0) d[dd]=dfs(dd);

v.push_back(d[dd]);

(我喜欢这么写清楚一点.... )这里要注意d[dd]要赋值,不然dfs跑一遍,返回一个ans要存储下来,不然浪费掉了

还有就是读入边的时候,不要读反了(最好画个图)

最后就是思路很重要,好好想想怎么实现,感觉还是挺神奇的

关于式子有点小问题,实验了一下,写成下面这种也可以,取整罢了。。。。

我最开始还被吓死了。。。答案是一样的,就是注意转换成double再ceil

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
int n; int p;
int a[100005];
int d[100005];
vector<int> g[100005];
int  dfs(int x) {
	// this time ,how will we start our journey
	//let's first find what we need
	// we got 0 at first , we want to see the sons of 0
	// and if it reaches the end(g[i]==0)
	//returns an ans
	if (g[x].size() == 0)return 1;
	// do you know that !  he is 1
	int sum = 0;
	vector<int> v;
	for (int i = 0; i<g[x].size(); i++) {
		int dd = g[x][i];
		if(d[dd]==0) 
			d[dd]=dfs(dd);
		v.push_back(d[dd]);
	
		//sum += dfs(dd);
	}
	
	///   辣鸡....
	/// size虽然也还是0,但是并没有改变dd的值.......
	///dfs(dd)返回了,但是dfs的值和d[dd]是不一样的...
	///注意到这里是没环的,所以直接加上吧... 都不用d数组了

	//没思路....
	//How to cal d[dd]?
	//只有自己一个节点是不能算的, 要从倒数第二个节点开始找
	//怎么找呢,首先是一个一个加,加到了cnt就可停下来了
	
	//for (int i = 0; i<g[x].size(); i++) {
	
	sort(v.begin(), v.end());
	int tmp = (g[x].size()*p - 1) / 100 + 1;
	///int tmp = ceil((p*g[x].size())/100);
	// if 40*3 we got 2
	for (int i = 0; i < tmp; i++) {
		sum += v[i];
	}
	return sum;
	cout << sum << endl;
}

//写错的时候当然要看自己有哪里不对.......   而不是疯狂调试........

int main() {
	while (cin >> n >> p) {
		if (n == 0 || p == 0)return 0;
		memset(d, 0, sizeof(d));
		for (int i = 0; i <= n; i++)g[i].clear();
		int u, v;
		for (int i = 1; i <= n; i++) {
			cin >> u;//just get father
					 // u is father
					 //BUT!!! DO  REMEMBER WHO IS U IN THE TITLE
					 //BUT!!! DO  REMEMBER WHO IS U IN THE TITLE
			g[u].push_back(i);
		//	cout << u << "-------" << g[u].size() << endl;
		}
		cout << dfs(0) << endl;
	}

	return 0;
}

HDU 1512 

另外,这个代码习惯不好。。。 不用if(xxx==0)bfs(xxx)直接后面的就好了

因为bfs里面是五环的(没有环 树上)

如果是无根的 双向边 可以加个-1访问标记(加个1的 bool比int快和省空间。。。。 )

还有注释写了一堆写的我好烦(不)一堆的写在外面  注释 在干嘛的写在里面

#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>
using namespace std;
int a[6005]; //happy- numbers
int n;
int fa[6005];// finds final father
int dp[6005][2];
vector<int>g[6005];
void dfs(int x) {
	//dp[x][1] = a[x];
	// 记得这里初始化!!!!!
	//if he goes we can get happy number like so
	//but he has many employee
	//so he needs to do many times

	int sum0 = 0;
	int sum1 = 0;
	for (int i = 0; i<g[x].size(); i++) {
		int d = g[x][i];

		if (dp[d][0] == 0 || dp[d][1] == 0)dfs(d);
		sum0 += max(dp[d][1], dp[d][0]);
		//0就是这位人不来,那么他的下属都来了,取得最大的
		sum1 += dp[d][0];
		//sum1就是这位爷来了,他的下属不能来了
		//但是下属会保持最好的dp[d][0] 传递上来
	}
	// 都跑完之后, 记录一下????哪里dp了
	// ???? 他的下属也可以不来
	//他的下属也可以不来
	//他的下属也可以不来
	//他的下属也可以不来
	dp[x][1] += sum1;
	dp[x][0] = sum0;
}

int main() {
	while (cin >> n) {

		memset(dp, 0, sizeof dp);
		memset(fa, -1, sizeof(fa));

		for (int i = 1; i <= n; i++)cin >> dp[i][1],g[i].clear();//happy numbers
		int u, v;
		while (cin >> u >> v) {
			// u is father
			if (u == 0 && v == 0)break;
			g[v].push_back(u);
			fa[u] = v;
		}
		//after that finds father first
		// go back for others

		int rec = 1;
		while (fa[rec] != -1)//if  have changed  continues searching
		{
			rec = fa[rec];
		}
		//fa[1]
		//***这里final fa其实是5
		//rec is the final father
		dfs(rec);//get all resulus
		cout << max(dp[rec][0], dp[rec][1]) << endl;
	}

	return 0;
}

HDU这个题.....  laji/....

Hdu是多组数据,,..  即使没说,用了while和memset就a了

终于明白这个是在讲什么了.. 没有数据的生活真的好苦(手再)

zj说 这需要经验 经验 经验

同样的标题 复制进去 找URAL交  accept

........但是人家数据不公开啊

hdu啊hdu(滑稽)

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值