标签:
如果状态定义为序号和重量的话,决策就是下一个垃圾捡或者不减,但是状态数太多了。
如果只定义序号作为状态的话,决策就变成从前面的某个j一直捡到i才送回垃圾。
这就变成了一个区间选最小值的问题,用单调队列维护。复杂度O(n)
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5+5; int x[maxn], y[maxn], w[maxn]; int sum_dist[maxn],sum_w[maxn],dist[maxn]; int dq[maxn],d[maxn]; inline int manhattan(int i,int j){ return abs(x[i]-x[j])+abs(y[i]-y[j]); } inline int f(int i) { return d[i] - sum_dist[i+1] + dist[i+1]; } //#define LOCAL int main() { #ifdef LOCAL freopen("in.txt","r",stdin); #endif //sum_dist[0] = 0;x[0] = y[0] = 0; d[0] = 0 dq[0] = 0 int T; scanf("%d",&T); while(T--){ int C,n; scanf("%d%d",&C,&n); for(int i = 1; i <= n; i++){ scanf("%d%d%d",x+i,y+i,w+i); if(i>1) sum_dist[i] = sum_dist[i-1] + manhattan(i,i-1); sum_w[i] = sum_w[i-1] + w[i]; dist[i] = manhattan(i,0); } int hd = 0,tl = 1; for(int i = 1; i <= n; i++){ while(tl>hd && sum_w[i] - sum_w[dq[hd]] > C) hd++; d[i] = f(dq[hd]) + (sum_dist[i] + dist[i]); while(tl>hd && f(i) <= f(dq[tl-1])) tl--; dq[tl++] = i; } printf("%d\n",d[n]); if(T) putchar(‘\n‘); } return 0; }
标签:
原文地址:http://www.cnblogs.com/jerryRey/p/4846949.html