题目大意:在一条直线上有n件珠宝,已知每件珠宝的位置,并且第 i 件珠宝在 ti 时刻就消失,问能否将所有的珠宝收集起来?如果能,求出最短时间。搜集能瞬间完成。
题目分析:区间DP。dp(i,j,0)表示搜集区间(i,j)并且停留在左端所需的最短时间,dp(i,j,1)表示搜集区间(i,j)并且停留在右端所需的最短时间。状态转移方程为
dp(i,j,0)=min(dp(i+1,j,0)+t(i+1)-t(i),dp(i+1,j1,)+t(j)-t(i)),dp(i,j,1)=min(dp(i,j-1,0)+t(j)-t(i),dp(i,j-1,1)+t(j)-t(j-1))。
这道题的数据规模比较大,可以用滚动数组优化空间复杂度。
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; int dp[2][10005][2]; int x[10005],t[10005],n; const int INF=0x7fffffff; int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;++i){ scanf("%d%d",x+i,t+i); dp[1][i][0]=dp[1][i][1]=dp[0][i][0]=dp[0][i][1]=(t[i]>0)?0:INF; } for(int i=n-2;i>=0;--i){ for(int j=i+1;j<n;++j){ dp[i&1][j][0]=dp[i&1][j][1]=INF; if(dp[(i&1)^1][j][0]!=INF&&dp[(i&1)^1][j][0]+x[i+1]-x[i]<t[i]) dp[i&1][j][0]=min(dp[i&1][j][0],dp[(i&1)^1][j][0]+x[i+1]-x[i]); if(dp[(i&1)^1][j][1]!=INF&&dp[(i&1)^1][j][1]+x[j]-x[i]<t[i]) dp[i&1][j][0]=min(dp[i&1][j][0],dp[(i&1)^1][j][1]+x[j]-x[i]); if(dp[i&1][j-1][0]!=INF&&dp[i&1][j-1][0]+x[j]-x[i]<t[j]) dp[i&1][j][1]=min(dp[i&1][j][1],dp[i&1][j-1][0]+x[j]-x[i]); if(dp[i&1][j-1][1]!=INF&&dp[i&1][j-1][1]+x[j]-x[j-1]<t[j]) dp[i&1][j][1]=min(dp[i&1][j][1],dp[i&1][j-1][1]+x[j]-x[j-1]); } } if(dp[0][n-1][1]==INF&&dp[0][n-1][0]==INF) printf("No solution "); else printf("%d ",min(dp[0][n-1][0],dp[0][n-1][1])); } return 0; }
下面这个是不加滚动数组的:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; int dp[10005][10005][2]; int x[10005],t[10005],n; const int INF=1000000000; int main() { while(~scanf("%d",&n)) { for(int i=0;i<n;++i) scanf("%d%d",x+i,t+i),dp[i][i][0]=dp[i][i][1]=0; for(int i=n-2;i>=0;--i){ for(int j=i+1;j<n;++j){ dp[i][j][0]=min(dp[i+1][j][0]+x[i+1]-x[i],dp[i+1][j][1]+x[j]-x[i]); if(dp[i][j][0]>=t[i]) dp[i][j][0]=INF; dp[i][j][1]=min(dp[i][j-1][0]+x[j]-x[i],dp[i][j-1][1]+x[j]-x[j-1]); if(dp[i][j][1]>=t[j]) dp[i][j][1]=INF; } } if(dp[0][n-1][1]==INF&&dp[0][n-1][0]==INF) printf("No solution "); else printf("%d ",min(dp[0][n-1][0],dp[0][n-1][1])); } return 0; }