題意:過n個加油站,沒站油價不等,問達到目的地的最小花費,其實100L油,到達終點至少100L油。
設狀態dp(i,j)表示在第i個加油站有jL油的最小花費,初始dp(i,j)=min{dp(i,j),dp(i-1,j+dis(i,i-1))},然後根據油價嘗試更新dp(i,k),(k>j)。
小心數據所給加油站並不是都在起點到終點的區間內。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int pos[110]={0},pri[110];
long long dp[110][210];
int main()
{
//freopen("in.txt","r",stdin);
int T;
cin>>T;
while(T--){
int dis,pre=0,n=1;
cin>>dis;getchar();
char t;
while((t=getchar())&&t!='\n'&&t!=EOF){
pos[n]=t-'0';
while((t=getchar())!=' ') pos[n]=pos[n]*10+t-'0';
pri[n]=0;
while((t=getchar())!='\n') pri[n]=pri[n]*10+t-'0';
if(pos[n]>0&&pos[n]<dis) n++;
}
n--;
bool is=true;
for(int i=2;i<n;i++) if(pos[i]-pos[i-1]>200){
is=false;break;
}
if(pos[1]>100) is=false;
if(pos[n]-pos[n-1]>100) is=false;
if(!is) {printf("Impossible\n");if(T) cout<<endl;continue;}
memset(dp,-1,sizeof(dp));
dp[0][100]=0;
for(int i=1;i<=n;i++){
int d=pos[i]-pos[i-1];
for(int j=0;d+j<=200;j++) if(dp[i-1][j+d]!=-1){
if(dp[i][j]==-1) dp[i][j]=dp[i-1][j+d];
else dp[i][j]=min(dp[i][j],dp[i-1][j+d]);
for(int k=1;j+k<=200;k++){
if(dp[i][j+k]==-1) dp[i][j+k]=dp[i][j]+pri[i]*k;
else dp[i][j+k]=min(dp[i][j+k],dp[i][j]+pri[i]*k);
}
}
}
long long ans=dp[n][dis-pos[n]+100];
if(ans==-1) cout<<"Impossible"<<endl;
else cout<<ans<<endl;
if(T) cout<<endl;
}
return 0;
}