方舟集群要进行第一次组合连接,使任意两个方舟之间都有通路连接。如果把现在的海域看作一个坐标系,那么x轴的正方向朝向正东,y轴的正方向朝向正北,在连接计划的开始,你可以选择海上或者方舟上的任意一点作为初始平台。坐标系上的整点都带有连接平台。出于安全性的考虑,一条通路的端点只能由连线平行于坐标轴的两个连接平台组成并且只能由已被初始平台连接的平台向正北和正东方向延伸。幸运的是,方舟排布是有规律的,对于编号为i的方舟和编号为j的方舟(i<j),满足xi<xj且yi>yj,所以你的任务就是找到连接计划花费的最小代价(代价即连接的通路的总长度)。
读完题目,我们首先可以发现一个显然的结论:初始平台的横坐标等于,纵坐标等于。那么我们能不能把一个区间内的方舟看成一个子问题,它的初始平台的横坐标等于,纵坐标等于,并将一个个子问题进行合并呢?为了验证这一猜想,我构造了一组样例。
我最初的想法是先枚举区间,再枚举断点,然后合并和。但一般的区间都是枚举断点,然后合并和,和我的状态转移方式不太吻合。我本来不信这个邪,交了一发,结果到分...看来还是要重视前人总结的经验啊...其实只要合并和,状态转移方程一目了然:
题目中,按理说的复杂度是过不了的,那么我们需要运用一个重要的优化:四边形不等式,即最优断点。要使用四边形不等式,首先要判断状态转移方程是否满足不等式的性质(然而我完全不会证)。在考场上如何快速判断呢?为节约宝贵的时间,我们可以在发现的复杂度过不了的时候考虑打表观察最优断点的位置,这样就免去了繁琐的证明。代码如下。
memset(dp,127,sizeof(dp));
for(int i=1;i<=n;i++) dp[i][i]=0,s[i][i]=i;//切记初始化
for(int len=2;len<=n;len++)
for(int l=1;l<=n-len+1;l++)
{
int r=l+len-1;
for(int k=s[l][r-1];k<=s[l+1][r];k++)
{
tmp=dp[l][k]+dp[k+1][r]+y[k]-y[r]+x[k+1]-x[l];
if(tmp<dp[l][r]) dp[l][r]=tmp,s[l][r]=k;
}
}