题目见

option=com_onlinejudge&Itemid=8&page=show_problem&problem=4681">here

题意:给一个序列arr[],你从中选择一些子序列,将子序列的值从左往右依次放到某棵二叉树的叶子节点上,使得除了叶子,全部节点左右子树权和相等。子树的权和 = 子树叶子的权和。

假设存在这样一棵二叉树,选择的子序列就是合法的。问,最长的合法子序列是多少。

思路:

枚举二叉树可能的叶子的最小权(入手点)。显然,能和此数一起组成二叉树的数,要么和这个数相等。要么是这个数的2^k倍。把满足这样的关系的数。认做一个集合,显然集合外的数,不能和集合内的数组成二叉树。那么,我们仅仅须要一个一个得求出全部集合的最长子序列就可以。

把集合内的所有数所有除以最小权。剩下的数为1,2,4,8,16,32,64.....这样的2^k的数。如果你从左到右。第一个填的数为16,第二个填的数一定不会比16大,不然那个16无法合并。如果填的就是16,那就合成为32。当然,填小于16的数也是行的。

那么,对于2^k的数。每一个数,在合并过程中一定仅仅有两种状态。有1个,或者没有。

那么我们似乎就能够用状态压缩就可。

具体见代码:

#include<algorithm>
#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1010;
typedef long long ll;
bool base[maxn*505],vis[505],iss[maxn];
int arr[maxn],dp[maxn*505],brr[maxn],sum[maxn];
int solve(int x,int n)
{
int i,j,lim,tp,ct=0,ans=0;
for(i=1;i<=n;i++)
if(arr[i]%x==0&&base[arr[i]/x])
brr[++ct]=arr[i]/x;
for(i=1;i<=ct;i++)
sum[i]=sum[i-1]+brr[i];
memset(dp,0xcf,sizeof dp);
dp[0]=0;
for(i=1;i<=ct;i++)
{
lim=2*brr[i];
for(j=sum[i];j>=lim;j--)
{
tp=j-brr[i];
if(!(tp&(brr[i]-1)))
dp[j]=max(dp[j],dp[tp]+1);
}
dp[brr[i]]=max(dp[brr[i]],1);
}
for(i=1;i<=sum[ct];i++)
if(base[i])
ans=max(ans,dp[i]);
return ans;
}
int main()
{
int n,i,j,lim,ans; lim=500*maxn;
for(i=1;i<lim;i<<=1)
base[i]=true;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;i++)
scanf("%d",&arr[i]);
memset(vis,0,sizeof vis);
for(i=1;i<=n;i++)
{
iss[i]=true;//是否叶子结点最小权值
if(vis[arr[i]])
{
iss[i]=false;
continue;
}
vis[arr[i]]=true;
for(j=1;j<=n;j++)
{
if(j==i)
continue;
if(arr[i]!=arr[j]&&arr[i]%arr[j]==0&&base[arr[i]/arr[j]])
{
iss[i]=false;
break;
}
}
}
ans=0;
for(i=1;i<=n;i++)
if(iss[i])
ans=max(ans,solve(arr[i],n));
printf("%d\n",ans);
}
return 0;
}

最新文章

  1. SHELL编写NGINX自动部署脚本
  2. Unity自动寻路Navmesh之入门
  3. 项目里面的某个资源文件(比如plist、音频等)无法使用
  4. iOS开发之UIAlertView与UIAlertController的详尽用法说明
  5. python中的进程、线程(threading、multiprocessing、Queue、subprocess)
  6. 用SecureCRT来上传和下载数据
  7. Android问题-新电脑新系统WIN764位上安装简版本的XE8提示“Unit not found: &#39;System&#39;”
  8. JavaScript中的[]和{}
  9. arm ldr 指令
  10. Javascript多线程引擎(三)
  11. 路由-when-resolve
  12. Python-进程与线程理论基础-Day10
  13. Linux内核高端内存
  14. 【Java】【13】两个double类型比较大小
  15. linux下目录简介——/sys
  16. ios 信任charles https 证书
  17. linqpad使用方法备忘
  18. 【原】Ubuntu13.04安装、卸载Gnome3.8
  19. Objective-C(生命周期)
  20. html5手机Web单页应用实践--起点移动阅读

热门文章

  1. axios的坑
  2. javascript的var声明变量和不用var声明变量在全局作用域的区别;
  3. 紫书 例题 11-13 UVa 10735(混合图的欧拉回路)(最大流)
  4. CentOS的基本设置界面
  5. svn文件管理器的使用
  6. 【codeforces 20B】Equation
  7. NYIST 1006 偷西瓜
  8. Win7操作系统防火墙无法关闭的问题 无法找到防火墙关闭的地方的解决的方法
  9. 获取当前最上层controller
  10. 25.不改变原生数据的STL algorithm