[ABC320F] Fuel Round Trip 题解
前言
纪念一下第一次做出 AT 评分 2000 的题,还有名字水色。
正文
0x00 题目分析
题意很简单就是要在从
可以发现这个题有两个难点:
-
需要返回
0 点,那么意味着来去选择的加油站会互相影响。 -
由于第一点引出了第二点加油站只能使用一次,那么很难设计一个 DP 状态,第一反应只是状压。
但是同时可以发现
对于这样的题可以先考虑去掉一些限制条件加上观察性质,找到一个大致的思路。
0x01 弱化版问题
假如不考虑需要返回
这里需要动一下脑筋,读者可以先想一下。
0x02 重新强化回去
观察到若只是需要走到
-
第
i 个加油站来时和返回时都不加油。 -
第
i 个加油站来时加油。 -
第
i 个加油站返回时加油。
转移方程显然。
0x03 代码实现
考虑刷表法,考虑
AC CODE
#include<bits/stdc++.h>
// #define ONLINE_JUDGE
#define INPUT_DATA_TYPE int
#define OUTPUT_DATA_TYPE long long
INPUT_DATA_TYPE read(){register INPUT_DATA_TYPE x=0;register char f=0,c=getchar();while(c<'0'||'9'<c)f=(c=='-'),c=getchar();while('0'<=c&&c<='9')x=(x<<3)+(x<<1)+(c&15),c=getchar();return f?-x:x;}void print(OUTPUT_DATA_TYPE x){register char s[20];register int i=0;if(x<0){x=-x;putchar('-');}if(x==0){putchar('0');return;}while(x){s[i++]=x%10;x/=10;}while(i){putchar(s[--i]+'0');}return;}
long long p[310],f[310],x[310],dp[310][310][310];
int main(){
#ifndef ONLINE_JUDGE
freopen("name.in", "r", stdin);
freopen("name.out", "w", stdout);
#endif
register int i,j,k;
register long long dis,tmp;
int n=read();
long long h=read(),res=0x3f3f3f3f3f3f3f3fll;
memset(dp,0x3f,sizeof(dp));
for(i=1;i<=n;++i) x[i]=read();
for(i=1;i<=n-1;++i) p[i]=read(),f[i]=read();
for(i=0;i<=h;++i)
dp[n][i][i]=0;
for(i=n-1;~i;--i){
for(j=0;j<=h;++j)
for(k=0;k<=h;++k){
dis=x[i+1]-x[i];
if(j+dis>h) continue;
if(k<dis) continue;
tmp=dp[i+1][j][k];
//case 0
dp[i][j+dis][k-dis]=std::min(dp[i][j+dis][k-dis],tmp);
//case 1
dp[i][std::max(j+dis-f[i],0ll)][k-dis]=std::min(dp[i][j+dis-f[i]][k-dis],tmp+p[i]);
//cass 2
dp[i][j+dis][std::min(k-dis+f[i],h)]=std::min(dp[i][j+dis][std::min(k-dis+f[i],h)],tmp+p[i]);
}
for(j=1;j<=h;++j)
for(k=h;k;--k)
dp[i][j][k]=std::min({dp[i][j][k],dp[i][j-1][k+1],dp[i][j][k+1],dp[i][j-1][k]});
}
for(i=0;i<=h;++i)
res=std::min(res,dp[0][h][i]);
print(res==0x3f3f3f3f3f3f3f3fll?-1:res);
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}
总结
这样的题需要加深对 DP 的理解,不能死板的套用常规 DP 的方式,而要根据题目要求具体分析设计状态。并且需要具备对问题的拆解、组合能力,把大问题简化,找到大问题和小问题之间的关联,往往能提供一个正确的大方向。