VOJOS1243-单调队列

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int NN=100005;
const int INF=0x7fffffff;

int m,n,c,l;
int a[6][NN],dp[6][NN];
int s[6][NN];
int q[6][6][NN],f[6][6],r[6][6]; //n*n个单调队列

int solve()
{
    for (int i=1; i<=n; i++)
    {
        dp[i][0]=-c;
        for (int j=1; j<=n; j++) 
        {
            f[i][j]=1;
            r[i][j]=1;
            q[i][j][1]=0;
        }
    }
    for (int j=1; j<=m; j++)
    {
        for (int i=1; i<=n; i++)
        {
            dp[i][j]=INF;
            for (int k=1; k<=n; k++)
            {
                if (i==k) continue;
                int *que=q[i][k];
                int &front=f[i][k];
                int &rear=r[i][k];
                while (front<=rear && que[front]+l<j) front++; //删除超出范围的队首
                dp[i][j]=min(dp[i][j],dp[k][que[front]]-s[i][que[front]]); 
            }
            dp[i][j]+=c+s[i][j];
        }
        for (int i=1; i<=n; i++)
        {
            for (int k=1; k<=n; k++)
            {
                if (k==i) continue;
                int *que=q[k][i]; //注意是k,i,而不是i,k,更新的dp[i]值备后续的更新dp[k]值所用
                int &front=f[k][i];
                int &rear=r[k][i];
                while (front<=rear && dp[i][que[rear]]-s[k][que[rear]]>=dp[i][j]-s[k][j]) rear--;
                que[++rear]=j;
            }
        }
    }
    int ans=INF;
    for (int i=1; i<=n; i++) ans=min(ans,dp[i][m]);
    return ans;
}

int main()
{
    scanf("%d%d%d%d",&m,&n,&c,&l);
    for (int i=1; i<=n; i++) s[i][0]=0;
    for (int i=1; i<=n; i++)
      for (int j=1; j<=m; j++)
      {
          scanf("%d",&s[i][j]);
          s[i][j]+=s[i][j-1];
      }
    printf("%d\n",solve());
    return 0;
}

你可能感兴趣的:(c,include)