http://acm.hdu.edu.cn/showproblem.php?pid=2829
HDU 2829 Lawrence
大意:
有一条直线型的铁路,上面有n个火车站,每个火车站有各自的权重a[i],
现有m枚炮弹,每枚炮弹可炸毁一段铁路。
已知整条铁路的权重W = sum(a[i]*a[j]),其中火车站编号i<j且i与j相连
问如何使用这m枚炮弹使W最小,输出最小的W值
分析:
sum[i]表示从1到i的权重和,包含i
cost[i][j]表示不炸毁[i,j]间的站点所需的花费,包含站点i和j
dp[i][k]表示从1到i炸毁k条路后所需的最少花费
则有:dp[i][k]=min(dp[j][k-1]+sum[j+1][i])(j=k,...,i-1)
用四边形不等式优化
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int N = 1000+5;
int sum[N];
int num[N];
int cost[N][N];
int s[N][N];
int dp[N][N];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)break;
int i,j,k;
memset(cost,0,sizeof(cost));
sum[0] = 0;
num[0] = 0;
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
sum[i]=sum[i-1]+num[i];
}
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
{
cost[i][j]=cost[i][j-1]+(sum[j-1]-sum[i-1])*num[j];
}
for(i=0;i<=n;i++)
{
s[i][0]=0;
dp[i][0]=cost[1][i];
}
for(k=1;k<=m;k++)
{
s[n+1][k]=n-1;
for(i=n;i>k;i--)
{
dp[i][k]=dp[k][k-1]+cost[k+1][i];
s[i][k]=k;
for(j=s[i][k-1];j<=s[i+1][k];j++)
{
int temp = dp[j][k-1]+cost[j+1][i];
if(temp<dp[i][k])
{
dp[i][k]=temp;
s[i][k]=j;
}
}
}
}
//cout<<dp[n][m]<<endl;
printf("%d\n",dp[n][m]);
}
return 0;
}