两份代码
第一份只能过后5个点
第二份能过全部点
原因是dp更新的时候弄错了。
hack数据:
5 2 1 1
1 1 1 1 1
5 5 5 5 5
正确答案 17
错误答案 13
总结,dp[i][j]要全部更新完之后,再去更新单调队列,否则会将其他人做的第i位的答案拿去更新自己的第i位的答案,这样是不对的。
第一份代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,K,l,T[100005][5],dp[100005][5],que[5][5][100005],st[5][5],ed[5][5],f[5][5][100005];
inline void push(int i,int j,int v,int p) {
while (st[i][j]<=ed[i][j]&&v<f[i][j][ed[i][j]])
--ed[i][j];
que[i][j][++ed[i][j]]=p;
f[i][j][ed[i][j]]=v;
}
inline int getMin(int p,int i,int j,int l) {
while (st[i][j]<=ed[i][j]&&que[i][j][st[i][j]]+l<p)
++st[i][j];
return f[i][j][st[i][j]];
}
int main()
{
scanf("%d%d%d%d",&m,&n,&K,&l);
for (int i=0;i<n;++i)
for (int j=1;j<=m;++j) {
scanf("%d",&T[j][i]);
T[j][i]+=T[j-1][i];
}
memset(dp,0x3f,sizeof dp);
for (int i=0;i<n;++i)
for (int j=0;j<n;++j)
if (i!=j)
push(i,j,-K,0);
for (int i=1;i<=m;++i) {
for (int j=0;j<n;++j) {
for (int k=0;k<n;++k)
if (k!=j)
dp[i][j]=min(dp[i][j],getMin(i,k,j,l)+K+T[i][j]);
for (int k=0;k<n;++k)
if (k!=j)
push(j,k,dp[i][j]-T[i][k],i);
}
}
int res=inf;
for (int i=0;i<n;++i)
res=min(res,dp[m][i]);
printf("%d\n",res);
return 0;
}
第二份代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,K,l,T[100005][5],dp[100005][5],que[5][5][100005],st[5][5],ed[5][5],f[5][5][100005];
inline void push(int i,int j,int v,int p) {
while (st[i][j]<=ed[i][j]&&v<f[i][j][ed[i][j]])
--ed[i][j];
que[i][j][++ed[i][j]]=p;
f[i][j][ed[i][j]]=v;
}
inline int getMin(int p,int i,int j,int l) {
while (st[i][j]<=ed[i][j]&&que[i][j][st[i][j]]+l<p)
++st[i][j];
return f[i][j][st[i][j]];
}
int main()
{
scanf("%d%d%d%d",&m,&n,&K,&l);
for (int i=0;i<n;++i)
for (int j=1;j<=m;++j) {
scanf("%d",&T[j][i]);
T[j][i]+=T[j-1][i];
}
memset(dp,0x3f,sizeof dp);
for (int i=0;i<n;++i)
for (int j=0;j<n;++j)
if (i!=j)
push(i,j,-K,0);
for (int i=1;i<=m;++i) {
for (int j=0;j<n;++j)
for (int k=0;k<n;++k)
if (k!=j)
dp[i][j]=min(dp[i][j],getMin(i,k,j,l)+K+T[i][j]);
for (int j=0;j<n;++j)
for (int k=0;k<n;++k)
if (k!=j)
push(j,k,dp[i][j]-T[i][k],i);
}
int res=inf;
for (int i=0;i<n;++i)
res=min(res,dp[m][i]);
printf("%d\n",res);
return 0;
}