题意
比赛时过的超级少,却是一道原题Orz,样例都没改
原题链接POJ1991
n个portal排成一排,给出他们的位置和冷却时间,现在从位置0,时间0开始,将所有portal hack一遍最后回到k最少时间是多少。移动1距离花费时间1,hack不费时间
题解
区间dp
首先,hack不费时间,那么对同一位置上的portal只保留最大冷却时间即可。
现在考虑一个区间[L,R],人站在区间的最左端,那么他hack L或R的portal是更优的,因为如果hack中间某个portal M,必须要走回到L再走到R或者走到R再走到L,这样的时间不会更优。因为后面的从L到R或从R到L都会再次经过M,这相比于先hack L或R反而多走了路,故而不会更优。因此对一段区间应先hack L或R。基于这个思路就可以区间dp了。
设状态
f[l][r][k]
,
k=0
表示区间
(l+1,r)
区间尚未访问,已经访问完
l
并站在
写代码时可以开两维,
f[l][r]
表示
f[l][r][0]
,
f[r][l]
表示
f[l][r][1]
代码
/// by ztx
/// blog.csdn.net/hzoi_ztx
#include <bits/stdc++.h>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v) for(i=v.begin();i!=v.end();i++)
#define r(x) read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
#define kN 1010LL
#define infi 0x3f3f3f3fLL
int n, m, pos, t[kN];
int idx, x[kN], f[kN][kN], ans;
inline void work() {
memset(f,0x3f,sizeof f);
memset(t,-1,sizeof t);
int i, j, k;
r(n), r(m), r(pos);
Rep (i,1,n) {
r(j), r(k);
if (k > t[j]) t[j] = k;
}
idx = 0;
Rep (i,0,m) if (~t[i]) x[++idx] = i;
f[1][idx] = std::max(x[1],t[x[1]]);
f[idx][1] = std::max(x[idx],t[x[idx]]);
Rev (k,idx-1,1) Rev(i,idx-k+1,1) {
j = i+k-1;
if (i == 1) {
f[i][j] = std::max(f[j+1][i]+x[j+1]-x[i],t[x[i]]);
f[j][i] = std::max(f[j+1][i]+x[j+1]-x[j],t[x[j]]);
} else if (j == n) {
f[i][j] = std::max(f[i-1][j]+x[i]-x[i-1],t[x[i]]);
f[j][i] = std::max(f[i-1][j]+x[j]-x[i-1],t[x[j]]);
} else {
f[i][j] = std::min(std::max(f[i-1][j]+x[i]-x[i-1],t[x[i]]),std::max(f[j+1][i]+x[j+1]-x[i],t[x[i]]));
f[j][i] = std::min(std::max(f[i-1][j]+x[j]-x[i-1],t[x[j]]),std::max(f[j+1][i]+x[j+1]-x[j],t[x[j]]));
}
}
ans = infi;
Rep (i,1,idx)
ans = std::min(ans,f[i][i]+std::abs(x[i]-pos));
printf("%d\n", ans);
}
int main() {
int T,kiss;
r(T);
Rep(kiss,1,T) printf("Case #%d: ",kiss), work();
END: getchar(), getchar();
return 0;
}