1. 程式人生 > >2018.10.21 bzoj1742: Grazing on the Run 邊跑邊吃草(區間dp)

2018.10.21 bzoj1742: Grazing on the Run 邊跑邊吃草(區間dp)

傳送門 區間dp入門題。

可以想到當前吃掉的草一定是一個區間(因為經過的草一定會吃掉)。 然後最後一定會停在左端點或者右端點。 f[i][j][0/1]f[i][j][0/1]表示已經吃了[i,j][i,j]的草,最後停在左/右端點。 利用費用提前計算的思想轉移就行了。 程式碼:

#include<bits/stdc++.h>
#define N 1005
#define ll long long
using namespace std;
ll f[N][N][2],l,pos[N];
int n;
inline int read(){
	int ans=0;
	char
ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar(); return ans; } int main(){ n=read(),l=read(); for(int i=1;i<=n;++i)pos[i]=read(); pos[++n]=l; sort(pos+1,pos+n+1); for(int i=1;i<=n;++i)f[i][i][0]=f[i][i][1]=abs(l-pos[
i])*n; for(int len=2;len<=n;++len){ for(int i=1;i<=n-len+1;++i){ int j=i+len-1; f[i][j][0]=min(f[i+1][j][0]+(n-len+1)*(pos[i+1]-pos[i]),f[i+1][j][1]+(n-len+1)*(pos[j]-pos[i])); f[i][j][1]=min(f[i][j-1][0]+(n-len+1)*(pos[j]-pos[i]),f[i][j-1][1]+(n-len+1)*(pos[j]-pos[j-1])); } } cout<<
min(f[1][n][0],f[1][n][1]); return 0; }