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;
}

 

posted @ 2014-04-17 10:17  wangyucheng  阅读(185)  评论(0编辑  收藏  举报