pku1160

pku1160
DP .首先求出任意两个村庄间(包括端点)建一个邮局后,到邮局的最短距离和,记为min_dis[i][j],当邮局建到中点时min_dis[i][j]最小. 用f[i][j]表示前i个邮局建在前j个村庄.则f[i][j]=min{f[i-1][k]+min_dis[k+1][j],i-1<=k<j}.见代码:
#include < iostream >
using   namespace  std;
int  v,p;
int  vill[ 305 ];
int  f[ 35 ][ 305 ];
int  min_dis[ 305 ][ 305 ];

int  main()
{
    
int i,j,k;
    scanf(
"%d%d",&v,&p);
    
for(i=1;i<=v;i++)
    scanf(
"%d",&vill[i]);
    memset(min_dis,
0,sizeof(min_dis));
    
for(i=1;i<=v;i++)
    
for(j=i+1;j<=v;j++)
    
{
        
int mid=(i+j)/2;
        
for(k=i;k<mid;k++)
        
{
            min_dis[i][j]
+=vill[mid]-vill[k];
        }

        
for(k=mid+1;k<=j;k++)
        
{
            min_dis[i][j]
+=vill[k]-vill[mid];
        }

    }

    
for(i=1;i<=v;i++) f[1][i]=min_dis[1][i];
    
for(i=2;i<=p;i++)
    
for(j=i;j<=v;j++)
    
{
        
int minn=100000000;
        
for(k=i-1;k<=j-1;k++)
        
{
            
if(f[i-1][k]+min_dis[k+1][j]<minn)
            minn
=f[i-1][k]+min_dis[k+1][j];
        }

        f[i][j]
=minn;
    }

    
    printf(
"%d\n",f[p][v]);
    
//system("pause");
    return 0;
}

你可能感兴趣的:(pku1160)