UVA1025 城市里的间谍 A Spy in the Metro
参照《算法竞赛入门经典(第二版)》,这上面写得很清楚。
核心代码如下:
for(int tim=t-1;tim>=0;tim--)
for(int sta=1;sta<=n;sta++){
dp[tim][sta]=dp[tim+1][sta]+1;
if(sta<n&<[sta][tim]&&tim+a[sta]<=t)
dp[tim][sta]=min(dp[tim][sta],dp[tim+a[sta]][sta+1]);
if(sta>1&&rt[sta][tim]&&tim+a[sta-1]<=t)
dp[tim][sta]=min(dp[tim][sta],dp[tim+a[sta-1]][sta-1]);
}
全部代码如下:
#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=55;
const int maxt=205;
int n,t,a[maxn],l,r,x,kase;
int lsum[maxn],rsum[maxn];
int lt[maxn][maxt],rt[maxn][maxt];
int dp[maxt][maxn];
int main(){
while(1){
cin>>n;
if(!n)return 0;
cin>>t;
for(int i=1;i<n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
lsum[i]=rsum[i]=0;
for(int i=2;i<=n;i++)
lsum[i]=lsum[i-1]+a[i-1];
for(int i=n-1;i>=1;i--)
rsum[i]=rsum[i+1]+a[i];
cin>>l;
memset(lt,0,sizeof(lt));
for(int i=1;i<=l;i++){
cin>>x;
for(int j=1;j<n&&x+lsum[j]<=t;j++)
lt[j][x+lsum[j]]=1;
}
cin>>r;
memset(rt,0,sizeof(rt));
for(int i=1;i<=r;i++){
cin>>x;
for(int j=n;j>1&&x+rsum[j]<=t;j--)
rt[j][x+rsum[j]]=1;
}
for(int i=0;i<=t;i++)
for(int j=1;j<=n;j++)
dp[i][j]=inf;
dp[t][n]=0;
for(int tim=t-1;tim>=0;tim--)
for(int sta=1;sta<=n;sta++){
dp[tim][sta]=dp[tim+1][sta]+1;
if(sta<n&<[sta][tim]&&tim+a[sta]<=t)
dp[tim][sta]=min(dp[tim][sta],dp[tim+a[sta]][sta+1]);
if(sta>1&&rt[sta][tim]&&tim+a[sta-1]<=t)
dp[tim][sta]=min(dp[tim][sta],dp[tim+a[sta-1]][sta-1]);
}
cout<<"Case Number "<<++kase<<": ";
if(dp[0][1]>=inf)puts("impossible");
else printf("%d\n",dp[0][1]);
}
return 0;
}
倒推十分巧妙。