比较重要的例题
滑动窗口+dp
很有意思找最小花费
用双向队列维护,仔细看看想想
每一次跑都从头跑,然后去排掉大的花销
dp思想
#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; }
优先队列重载函数写法
struct G { int s,w; int id; }a[N]; class cmp{ public: bool operator() (G& x,G& y) { if(x.s==y.s) return x.id>y.id; return x.s<y.s; } }; priority_queue<G,vector<G>,cmp> mp;
结构体内置排序函数写法
struct G{ int s,w,id; bool operator<(const G &t)const { if(t.s==s) return id<t.id; return s>t.s; }// 直接在结构体里排序方法,外面就不需要写cmp了,直接sort排序即可 };