BZOJ 1495: [NOI2006]网络收费 树形DP+复杂度分析
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls x<<1
#define rs x<<1|1
#define N 2105
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n;
ll ans;
int tp[N],B[20],s[20];
ll cost[N][12],f[N][N],C[N][2];
int lca(int x,int y)
{
int i;
for(i=n-1;i>=0;--i) if((x>>i)!=(y>>i)) break;
return n-i-1;
}
void dfs(int x,int dep)
{
if(dep==n)
{
f[x][0]=C[x-B[n]][0];
f[x][1]=C[x-B[n]][1];
for(int i=0;i<dep;++i) f[x][s[i]^1]+=cost[x-B[n]][i];
return;
}
s[dep]=0;
memset(f[x],0x3f,sizeof(f[x][0])*(B[n-dep]+1));
dfs(ls,dep+1),dfs(rs,dep+1);
for(int i=0;i<=B[n-dep-1];++i) for(int j=0;i+j<=B[n-dep-1];++j)
f[x][i+j]=min(f[x][i+j],f[ls][i]+f[rs][j]);
s[dep]=1;
dfs(ls,dep+1),dfs(rs,dep+1);
for(int i=1;i<=B[n-dep-1];++i) for(int j=B[n-dep-1]+1-i;j<=B[n-dep-1];++j)
f[x][i+j]=min(f[x][i+j],f[ls][i]+f[rs][j]);
}
int main()
{
// setIO("input");
scanf("%d",&n);
int i,j,v,a;
for(i=0;i<=n;++i) B[i]=1<<i;
for(i=0;i<B[n];++i) scanf("%d",&tp[i]);
for(i=0;i<B[n];++i) C[i][tp[i]]=0,scanf("%d",&C[i][tp[i]^1]);
for(i=0;i<B[n];++i) for(j=i+1;j<B[n];++j)
{
a=lca(i,j),scanf("%d",&v);
cost[i][a]+=v,cost[j][a]+=v;
}
dfs(1,0);
ans=1ll<<60;
for(i=0;i<=B[n];++i) ans=min(ans,f[1][i]);
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号