• 最短路之和 解题报告


    最短路之和

    也许是一个常见套路,然而我并不会...

    考虑这个(2 imes n)的格子形成的树的结构

    任意相邻的两列都有一条边或者两条边,称两条边的相邻两列为联通,联通具有传递性。

    性质:在一个联通列中,有且仅有一条竖边

    于是可以按联通性进行划分进而dp

    比如这个图就划分出了5个联通块

    对于这个题,首先按边统计贡献,每个边贡献为(sum(sum-x))(sum)是总点权,(x)是这个边任意一侧的点权和。

    然后做dp就好了,(dp_{i,0/1})表示(i)(i+1)列只连一条边的最小价值

    [dp_{n,br}=min_{m,bl} (dp_{m-1,bl}+cost(m,n,bl,br)) ]

    后面的(cost)随便(O(n))算一算就好了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #define ll long long
    using std::min;
    const int N=52;
    template <class T>
    void read(T &x)
    {
        x=0;char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    ll a[2][N],fl[N],fr[N],sum,dp[N][2];
    ll cost(int n,int br,int m,int bl)
    {
    	if(n==m)
    	{
    		a[bl][m]+=fl[m-1];
    		a[br][n]+=fr[n+1];
    		ll mi=a[bl][m]*(sum-a[bl][m]);
    		a[bl][m]-=fl[m-1];
    		a[br][n]-=fr[n+1];
    		return mi;
    	}
    	a[bl][m]+=fl[m-1];
    	a[br][n]+=fr[n+1];
    
    	ll sup=0,sdow=0,yuy=0,sumdow=0,mi=1e18;
    	for(int i=n;i>m;i--)
    	{
    		sup+=a[0][i];
    		sdow+=a[1][i];
    		yuy+=sup*(sum-sup);
    		yuy+=sdow*(sum-sdow);
    		sumdow+=a[1][i];
    	}
    	sumdow+=a[1][m];
    	sdow+=a[1][m];
    	sup+=a[0][m];
    	ll dl=0;
    	for(int i=m;i<=n;i++)
    	{
    		yuy+=sumdow*(sum-sumdow);
    		mi=min(yuy,mi);
    		yuy-=sumdow*(sum-sumdow);
    
    		sdow-=a[1][i];
    		sup-=a[0][i];
    
    		yuy-=sdow*(sum-sdow);
    		dl+=a[1][i];
    		yuy+=dl*(sum-dl);
    
    		yuy-=sup*(sum-sup);
    		yuy+=(sup+sumdow)*(sum-sup-sumdow);
    	}
    
    	a[bl][m]-=fl[m-1];
    	a[br][n]-=fr[n+1];
    	return mi;
    }
    void work()
    {
        int n;
    	read(n);sum=0;ll su=0;
    	for(int i=1;i<=n;i++) read(a[0][i]),sum+=a[0][i];
    	for(int i=1;i<=n;i++) read(a[1][i]),sum+=a[1][i];
    	fr[n+1]=0;
    	for(int i=n;i;i--) fr[i]=fr[i+1]+a[0][i]+a[1][i];
    	for(int i=1;i<=n;i++) fl[i]=fl[i-1]+a[0][i]+a[1][i];
    	memset(dp,0x3f,sizeof dp);
    	dp[0][0]=dp[0][1]=0;
    	for(int i=1;i<=n;i++)
    	{
    		su+=a[0][i]+a[1][i];
    		for(int j=1;j<=i;j++)
    		{
    			dp[i][0]=min(dp[i][0],dp[j-1][0]+cost(i,0,j,0));
    			dp[i][0]=min(dp[i][0],dp[j-1][1]+cost(i,0,j,1));
    			dp[i][1]=min(dp[i][1],dp[j-1][0]+cost(i,1,j,0));
    			dp[i][1]=min(dp[i][1],dp[j-1][1]+cost(i,1,j,1));
    		}
    		dp[i][0]+=su*(sum-su);
    		dp[i][1]+=su*(sum-su);
    	}
    	printf("%lld
    ",dp[n][0]);
    }
    int main()
    {
        //freopen("sum.in","r",stdin);
        //freopen("sum.out","w",stdout);
    	int T;read(T);
    	while(T--) work();
    	return 0;
    }
    

    2019.3.23

  • 相关阅读:
    WCF 无法生成 client
    Powershell profile.ps1 cannot be loaded because its operation is blocked by software restriction policies
    信步拾遗之Windwos Live Writer插件
    Maven setting.xml文件详解(转)
    Maven pom.xml详解(转)
    信步漫谈之Maven—基础介绍
    信步漫谈之Nginx—负载均衡
    信步漫谈之Hibernate—基础介绍
    信步漫谈之Dom4j—基础介绍
    信步拾遗之CHM开源文档制作
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10586028.html
Copyright © 2020-2023  润新知