zoukankan      html  css  js  c++  java
  • P3262 [JLOI2015]战争调度

    题解

    由于这是一棵满二叉树,所以其树高只有 (n)

    (f_{i,j,S})(i) 的子树内,有 (j) 个平民参战,且 (operatorname{fa}(i)sim 1) 的路径上的点,颜色为 (S) 的对应二进制位。转移就是普通的树上背包。

    乍一看时间复杂度不太对,但 (f) 只有 (sum_{i=1}^n 2^i imes 2^{n-i} imes 2^i) 个状态;一个状态 ((i,j,S)) 的转移复杂度是 (mathcal{O}(j))。于是总复杂度是 (mathcal{O}(n4^n))

    但这样 (f) 比较难存储,发现可以把 (S) 通过 dfs 砍掉。

    Bonus:应该可以通过上下界优化,让时间复杂度变成 (mathcal{O}(4^n))

    代码

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
    #define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
    template<typename T>
    void Read(T &_x){
    	_x=0;int _f=1;
    	char ch=getchar();
    	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
    	while(isdigit(ch)) _x=_x*10+(ch^48),ch=getchar();
    	_x*=_f;
    }
    template<typename T,typename... Args>
    void Read(T &_x,Args& ...others){
    	Read(_x);Read(others...);
    }
    typedef long long ll;
    const int Vertex=1030;
    int n,m,son[Vertex][2],fa[Vertex],dep[Vertex],cont[Vertex][Vertex][2];
    ll f[Vertex][Vertex];
    void Dfs(int u,int stat){
    	memset(f[u],0,sizeof(f[u]));
    	if(!son[u][0]){
    		for(int v=fa[u],st=stat;v;v=fa[v],st>>=1){
    			if(st&1) f[u][1]+=cont[u][v][1];
    			else f[u][0]+=cont[u][v][0];
    		}
    		return;
    	}
    	For(i,0,1){
    		Dfs(son[u][0],stat<<1|i);
    		Dfs(son[u][1],stat<<1|i);
    		int mx=(1<<(n-dep[u]));
    		For(j,0,min(mx,m)){
    			For(k,0,j){
    				f[u][j]=max(f[u][j],f[son[u][0]][k]+f[son[u][1]][j-k]);
    			}
    		}
    	}
    }
    int main(){
    	Read(n,m);
    	For(i,1,(1<<(n-1))-1) son[i][0]=i<<1,son[i][1]=i<<1|1;
    	For(i,1,(1<<n)-1) fa[i]=i/2,dep[i]=dep[fa[i]]+1;
    	For(i,1,1<<(n-1)){
    		int u=(1<<(n-1))+i-1,v=fa[u];
    		For(j,1,n-1){
    			int x;Read(x);
    			cont[u][v][1]=x;
    			v=fa[v];
    		}
    	}
    	For(i,1,1<<(n-1)){
    		int u=(1<<(n-1))+i-1,v=fa[u];
    		For(j,1,n-1){
    			int x;Read(x);
    			cont[u][v][0]=x;
    			v=fa[v];
    		}
    	}
    	Dfs(1,0);
    	ll ans=0;
    	For(i,0,m) ans=max(ans,f[1][i]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
    Written by Alan_Zhao
  • 相关阅读:
    Oracle 推出 ODAC for Entity Framework 和 LINQ to Entities Beta版
    Entity Framework Feature CTP 5系列文章
    MonoDroid相关资源
    MSDN杂志上的Windows Phone相关文章
    微软学Android Market推出 Web Windows Phone Marketplace
    使用 Visual Studio Agent 2010 进行负载压力测试的安装指南
    MonoMac 1.0正式发布
    Shawn Wildermuth的《Architecting WP7 》系列文章
    使用.NET Mobile API即51Degrees.mobi检测UserAgent
    MongoDB 客户端 MongoVue
  • 原文地址:https://www.cnblogs.com/alan-zhao-2007/p/p3262-sol.html
Copyright © 2011-2022 走看看