我只过了样例和 #21。
做法是枚举起点,然后计算 dpi 代表前 i 个单位时间能获得的最大收益。
单调队列优化,每次弹出所有满足 i−j≥p 的 j。
同一条道路上的金币是否会消失?
比如说时刻 1 出现了 3 个,时刻 2 出现了 4 个,那么如果时刻 2 收集,是收集 4 个吗?
求助 /bx /bx /bx
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define REP(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define mkpr make_pair
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
template<class T>
void ckmx(T& a,T b){
a=max(a,b);
}
template<class T>
void ckmn(T& a,T b){
a=min(a,b);
}
template<class T>
T gcd(T a,T b){
return !b?a:gcd(b,a%b);
}
template<class T>
T lcm(T a,T b){
return a/gcd(a,b)*b;
}
#define gc getchar()
#define eb emplace_back
#define pc putchar
#define ep empty()
#define fi first
#define se second
#define pln pc('\n');
template<class T>
void wrint(T x){
if(x<0){
x=-x;
pc('-');
}
if(x>=10){
wrint(x/10);
}
pc(x%10^48);
}
template<class T>
void wrintln(T x){
wrint(x);
pln
}
template<class T>
void read(T& x){
x=0;
int f=1;
char ch=gc;
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=gc;
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
x*=f;
}
const int maxn=1005;
int n,m,p;
ll dp[maxn*2];
ll reward[maxn][2*maxn];
ll cost[maxn];
/*
注意到,确定起点之后,只需要根据时间就可以得到位置
考虑枚举起点。
然后,dp[i] 代表前 i 个单位的时间走完的最大收益
枚举时间,每次新加入 len=1 的一个单位,同时此前已经加入的,代价全部加上一个定值
同时,将 i-j>p 的删掉
*/
int lst(int i,int dis){
return ((i-1-dis)%n+n)+1;
}
void solve(int id_of_test){
read(n);
read(m);
read(p);
FOR(i,1,n){
FOR(j,1,m){
read(reward[i][j]);
}
}
FOR(i,1,n){
read(cost[i]);
}
ll ans=-1e18;
FOR(s,1,n){
// s = 起点位置
FOR(i,1,m+p)dp[i]=-1e9;
deque<pll> rem;// fi:代价,se:终止时间
ll add=0;
FOR(time,1,m+p){//需要注意,这个得扩展
int nw_pos=(s-1+time-1)%n+1;// 现在走到了哪个点
while(!rem.empty()&&time-rem.front().se>=p)rem.pop_front();
add+=reward[nw_pos][time];
ll nw=dp[time-1]+reward[nw_pos][time]-cost[nw_pos]-add;
while(!rem.empty()&&nw>=rem.back().fi)rem.pop_back();
rem.push_back(mkpr(nw,time));
dp[time]=rem.front().fi+add;
}
ckmx(ans,*max_element(dp+1,dp+m+p+1));
}
printf("%lld\n",ans);
}
int main()
{
int T;
T=1;
FOR(_,1,T){
solve(_);
}
return 0;
}