P5017 摆渡车

· · 题解

介绍一个并没有很好的方法,复杂度O(n^2m)比很多人慢了点,实测380ms

具体思路是这么来的:

感觉思路好像很严密的样子,草草写完一交,却发现只拿了55分。

问题出现在哪里?

  1. 假设错误 \rightarrow 我误以为第车一定会在第j个人来到的时候开出,但实际上车都不一定会在第i个人来的时候开出(因为车可能还在路上)
  2. 边界要注意,t[0]赋初值为-Inf

这样分析之后,我们优化一下思路:

最终答案就在A[n][i]中取个min就好了,i\in [0,m]

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define debug(x) cout<<#x<<"="<<x<<endl
typedef long long ll;
using namespace std;
const int Inf=0x3f3f3f3f;
const int Maxn=1000;
const int Maxm=200;
int n,m;
int t[Maxn];
int A[Maxn][Maxm];
int Wait[Maxn][Maxn];
inline int read()
{
    int rt=0,fl=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') fl=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){rt=rt*10+ch-'0';ch=getchar();}
    return rt*fl;
}
void read_ini()
{
    memset(A,0x3f,sizeof(A));
    n=read(); m=read();
    for(int i=1;i<=n;i++) t[i]=read();
    sort(t+1,t+1+n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++) 
            for(int k=j;k<=i;k++) Wait[j][i]+=t[i]-t[k];
    for(int i=0;i<=m;i++) A[1][i]=i,A[0][i]=0;
    t[0]=-Inf;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<i;j++)
        {    
            for(int k=0;k<=m;k++)
            {
                if(k+m+t[j]<=t[i])
                {
                    A[i][0]=min(A[i][0],A[j][k]+Wait[j+1][i]); 
                }
                else
                {
                    A[i][k+m+t[j]-t[i]]=min(A[i][k+m+t[j]-t[i]],A[j][k]+Wait[j+1][i]+(i-j)*(k+m+t[j]-t[i]));
                }
            }
        }
    }
    int ans=Inf;
    for(int i=0;i<=m;i++) ans=min(ans,A[n][i]);
    printf("%d\n",ans);
}
int main()
{
    read_ini();
    return 0;
}

整体来说,题目难度不是很大,但是细节比较多,需要更细心一点,祝大家RP++