noi2006 网络收费
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> using namespace std; int nn,n; #define N 1050 #define inf 0x6fffffffffffLL typedef long long ll; ll dp[N*2][2500]; int c[N]; int f[N][N]; int a[N]; ll cost[N][25];int siz[N*2]; int main(){ scanf("%d",&nn); n=(1<<nn); for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]^=1; for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){ scanf("%d",&f[i][j]); f[j][i]=f[i][j]; } for(int i=1;i<n*2;i++){ int z=0; for(;(1<<z)<=i;z++); siz[i]=nn-z+1; } for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(i!=j){ int now=i^j; int z=0; for(;(1<<z)<=now;z++); cost[i+1][z]+=f[i+1][j+1]; } for(int i=1;i<=n;i++){ int x=i+n-1; for(int j=0;j<(1<<nn);j++){ for(int z=1;z<=nn;z++)if((1<<z-1)&j)dp[x][j]+=cost[i][z]; else dp[x][j+(1<<nn)]+=cost[i][z]; if(a[i])dp[x][j]+=c[i]; else dp[x][j+(1<<nn)]+=c[i]; } } for(int i=n-1;i>=1;i--){ for(int j=0;j<(1<<nn+1);j++)dp[i][j]=inf; for(int j=0;j<(1<<nn+1);j++){ int num=(j>>(nn-siz[i])); if(num>(1<<siz[i]))continue; int fa=j^(num<<(nn-siz[i])); if(num>=(1<<siz[i]-1)){ for(int z=num-(1<<siz[i]-1);z<=(1<<siz[i]-1);z++){ dp[i][j]=min(dp[i][j],dp[i<<1][(z<<(nn-siz[i]+1))+(fa<<1)+1]+dp[(i<<1)+1][((num-z)<<(nn-siz[i]+1))+(fa<<1)+1]); } }else{ for(int z=0;z<=num;z++){ dp[i][j]=min(dp[i][j],dp[i<<1][(z<<(nn-siz[i]+1))+(fa<<1)]+dp[(i<<1)+1][((num-z)<<(nn-siz[i]+1))+(fa<<1)]); } } } } ll ans=inf;for(int j=0;j<=n;j++){ ans=min(ans,dp[1][j]); } cout<<ans; }