cqoi2017,bzoj4813小Q的棋盘(树形dp或瞎搞)

1.前言

我现在很气。

考试的时候想着写树形dp,结果因为脑残以为要多叉转二叉而写挂了。挂了之后我瞎搞一通,结果居然50分,我特别奇怪地加了个步数可以把整棵树走一边就输出n的特判,就蜜汁AC了,这!什!么!鬼!题!!!!!!

好吧,后来发现可以证明我的贪心是对的,也就是说树形dp什么的完全是我想多了。

反正我觉得我要滚粗了,连重庆的水题都做不出。

2.贪(xia)心(gao)做法(100分,O(n))

可以证明,除了树上最长链以外的每一个节点都可以”看作“两步到达。感性的思路就是:走到最长链上是不要返回的,假如最优解中还要经过一些非最长链上的点,先走最长链,走到可以到达这些点的地方走一遍这些点,返回,因为要返回所以两步到达,在最长链上不返回肯定最优。(理性的思路:安大神犇居然还在坐标系里建立关于深度的函数证明了,反正我弱我不会)

所以我们就得到了贪心做法:

1.走不完最长链,就是步数

2.走的完整棵树,就是n

3.否则就是(步数-最长链)/2+最长链

#include
#include
#include
#include
#include
#include
#include
using namespace std;
vectorlu[105];
int deep[105];
bool vis[105];
int n,v,ans,bj,mx=0;
int read(){
	char ch=' ';int w=1,p=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')p=p*10+ch-'0',ch=getchar();
	return p*w;
}
void dfs(int x,int d,int las){
	int sz=lu[x].size(),i;
	mx=max(d,mx);deep[x]=d;
	for(i=0;i
3.树形dp做法(100分,O(nm^2))

树形dp做法就比较直观了,这题连多叉转二叉都用不上,直接一个树上的01背包搞定。

有三种走法:

1.左边走一些链并回来,右边走一些链不回来

2.左边走一些链不回来,右边走一些链并回来

3.左边走一些链回来,右边走一些链回来

注意到最后对于每一个步数,里面存的值应该赋值为小于这个步数的所有步数最优值

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int g[105][105],f[105][105];//g:回来,f:不回来
int read(){
	char ch=' ';int w=1,q=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();
	return w*q;
}
int n,v;
vectorlu[105];
void dfs(int x,int las){
	int i,j,k,sz=lu[x].size();
	g[x][0]=f[x][0]=1;
	for(i=0;i=1;j--){//树上的01背包
			for(k=1;k<=j;k++){
				if(k>=2)g[x][j]=max(g[x][j],g[lu[x][i]][k-2]+g[x][j-k]);//左边回右边回
				f[x][j]=max(f[x][j],f[lu[x][i]][k-1]+g[x][j-k]);//左边不回右边回
				if(k>=2)f[x][j]=max(f[x][j],g[lu[x][i]][k-2]+f[x][j-k]);//左边回右边不回
			}
		}
	}
	for(i=2;i<=v;i++)g[x][i]=max(g[x][i-1],g[x][i]);//注意这里!!!不一定要步数正好一样
	for(i=2;i<=v;i++)f[x][i]=max(f[x][i-1],f[x][i]);
}
int main()
{
   	int i,j,x,y;
   	n=read();v=read();
   	for(i=1;i<=n-1;i++){
   		x=read();y=read();
   		lu[x+1].push_back(y+1);lu[y+1].push_back(x+1);
   	}
   	dfs(1,0);
   	printf("%d",f[1][v]);
   	return 0;
} 

4.后记

我要滚粗了~这次省选绝对挂了~

我好弱呀怎么办呀~~~~~


你可能感兴趣的:(动态规划,瞎搞)