解释的越清楚越好。建议给我解释的时候先看看下面一长段文字。
重锁粥汁Floyd需要枚举3个玩意儿,一个是起点一个是终点,还有一个跳点
我记得刚开始学的时候是k(跳点),然后依次是i(起点),j(终点),
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
然后后来题目做多了,自己总结出一个规律,dp的循环枚举顺序取决于两个东西,一个是dp的定义,决定要枚举些什么玩意儿,还有一个是dp转移方程,决定枚举循环的顺序。如果dp ...转移到了另一个dp ...,那么如果你期望这个地方是被算过的,你的循环顺序就应当是可以使其被算过。也就是转移到的地方要不要算。
举个例子:
设dp i,j表示下标为i起点,长度j格的一些情况
然后dp i,j很明显枚举一个中间把这个区间劈开的点i+k,然后左边右边劈一半加起来就是了。
dp i j=max(dp[i][j],dp[i][k]+dp[i+k][j-k])
那么如果要计算dp 1 5,其中会用到一个dp 1 3和dp 4 2。
如果循环是这样的:
for(int i=1;i<=n;++i)
for(int w=1;i+w-1<=n;++w)
for(int k=1;k<w;++k)
dp[i][w]=max(dp[i][w],dp[i][k]+dp[i+k][j-k]);
会发现在计算dp 1 5时,dp 4 2没有被计算。就导致结果出错。
所以我在进行区间dp的时候,一般将区间长度放在最外面。
不排除有别的实现区间dp的方法。
那么在Floyd的时候,感觉把跳点放在里面枚举的时候转移到的都是计算过的啊。
求一组hack数据以及详细解释(计算什么的时候什么没被计算导致出错)。