比較重要的例題

發表於2024-03-15

滑動視窗+dp

很有意思找最小花費

用雙向佇列維護,仔細看看想想

每一次跑都從頭跑,然後去排掉大的花銷

dp思想

Problem - E - Codeforces

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=2e5+5,M=1e9+7;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

int a[105][N];
void solve()
{
    int n,m,k,d;
    cin>>n>>m>>k>>d;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    vector<int> sum;
    for(int i=1;i<=n;i++)
    {
        deque<int> q;
        int dp[m+2];
        dp[1]=1;
        q.push_back(1);
        for(int j=2;j<=m;j++)
        {
            while (!q.empty() && j-q.front()-1>d) q.pop_front();
            dp[j]=dp[q.front()]+a[i][j]+1;
            while (!q.empty() && dp[q.back()]>dp[j]) {
                q.pop_back();
            }
            q.push_back(j);
        }
        sum.push_back(dp[m]);
    }
    int pp[N];
    pp[0]=sum[0];
    for(int i=1;i<sum.size();i++)
    {
        pp[i]=pp[i-1]+sum[i];
    }
    int ans=pp[k-1];
    for(int i=k;i<sum.size();i++)
    {
        ans=min(ans,pp[i]-pp[i-k]);
    }
    cout<<ans<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

相關文章