非常感谢Atcoder提供dp专项比赛,题目都不错(虽然都是一些很有名的题目
迟到1小时的本人打了2小时才过了13题,。。。(打完O就睡觉去了
后来发现是场Unrated比赛? 666
dp还真的挺有趣的
A Frog1
大水题
d p [ i ] dp[i] dp[i]表示到达i的最小花费
d p [ i ] = m i n ( d p [ i − 1 ] + ∣ a [ i ] − a [ i − 1 ] ∣ , d p [ i − 2 ] + ∣ a [ i ] − a [ i − 2 ] ) dp[i]=min(dp[i-1]+|a[i]-a[i-1]|,dp[i-2]+|a[i]-a[i-2]) dp[i]=min(dp[i−1]+∣a[i]−a[i−1]∣,dp[i−2]+∣a[i]−a[i−2])
时间复杂度O(n)
啊比赛开场不在状态,忘记 d p [ 0 ] = i n f dp[0]=inf dp[0]=inf导致 w a wa wa了2发罚了 10 m i n 10min 10min
哭啊
int n ;
ll a[N], dp[N] ;
signed main(){
scanf("%d", &n) ;
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]) ;
for (int i = 0; i <= n; i++) dp[i] = linf ;
dp[1] = 0ll ;
for (int i = 2; i <= n; i++)
dp[i] = min(dp[i], min(dp[i - 1] + abs(a[i] - a[i - 1]), dp[i - 2] + abs(a[i] - a[i - 2]))) ;
printf("%lld\n", dp[n]) ;
return 0 ;
}
B - Frog 2
也还是一样的
d p [ i ] = min j = 1 m i n ( i − 1 , k ) d p [ i − j ] + a b s ( a [ i ] − a [ i − j ] ) dp[i]=\min_{j=1}^{min(i-1,k)}dp[i-j]+abs(a[i]-a[i-j]) dp[i]=minj=1min(i−1,k)dp[i−j]+abs(a[i]−a[i−j])
O(nk)
int n, k ;
ll a[N], dp[N] ;
signed main(){
scanf("%d%d", &n, &k) ;
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]) ;
for (int i = 0; i <= n; i++) dp[i] = linf ;
dp[1] = 0ll ;
for (int i = 2; i <= n; i++)
for (int j = 1; j <= min(i - 1, k); j++)
dp[i] = min(dp[i], dp[i - j] + abs(a[i] - a[i - j])) ;
printf("%lld\n", dp[n]) ;
return 0 ;
}
C - Vacation
依然是入门难度的
d p [ i ] [ j ] dp[i][j] dp[i][j]表示玩到第 i i i天,当天玩的是 j j j项目的最大值
d p [ i + 1 ] [ k ] = m i n ( d p [ i + 1 ] [ k ] , d p [ i ] [ j ] + a [ i + 1 ] [ k ] ) dp[i+1][k]=min(dp[i+1][k],dp[i][j]+a[i+1][k]) dp[i+1][k]=min(dp[i+1][k],dp[i][j]+a[i+1][k])
a n s = min i = 1 3 d p [ n ] [ i ] ans=\min_{i=1}^3dp[n][i] ans=mini=13dp[n][i]
时间复杂度O(n)
int n, ans ;
int a[N][4], dp[N][4] ; // dp[i][j]表示玩到第i天,当天玩的是j项目的最大值
signed main(){
scanf("%d", &n) ;
for (int i = 1; i <= n; i++) scanf("%d%d%d", &a[i][1], &a[i][2], &a[i][3]) ;
for (int i = 1; i <= n; i++) dp[i][1] = dp[i][2] = dp[i][3] = -iinf ;
for (int i = 1; i <= 3; i++) dp[1][i] = a[1][i] ;
for (int i = 1; i < n; i++)
for (int j = 1; j <= 3; j++)
for (int k = 1; k <= 3; k++)
if (j != k)
dp[i + 1][k] = max(dp[i + 1][k], dp[i][j] + a[i + 1][k]) ;
for (int i = 1; i <= 3; i++) ans = max(ans, dp[n][i]) ;
printf("%d\n", ans) ;
return 0 ;
}
D - Knapsack 1
01背包纯模板题
直接打就是了
int n, m ;
ll f[N], w[N], v[N] ;
signed main(){
scanf("%d%d", &n, &m) ;
for (int i = 1; i <= n; i++) scanf("%lld%lld", &w[i], &v[i]) ; // height and value
memset(f, 0xcf, sizeof(f)) ;
f[0] = 0 ;
for (int i = 1; i <= n; i++)
for (int j = m; j >= w[i]; j--)
f[j] = max(f[j], f[j - w[i]] + v[i]) ;
ll ans = 0 ;
for (int j = 0; j <= m; j++) ans = max(ans, f[j]) ;
printf("%lld\n", ans) ;
return 0 ;
}
E - Knapsack 2
物品体积很大,不能按照原先的 d p dp dp方程去 d p dp dp了
但是物品的价值最大才 1 0 5 10^5 105
于是我们能够轻松地想出 d p dp dp方程:
d p [ i ] dp[i] dp[i]表示达到 i i i的价值最少需要多大的体积
d p [ j ] = m i n ( d p [ j − v [ i ] ] + w [ i ] ) dp[j]=min(dp[j-v[i]]+w[i]) dp[j]=min(dp[j−v[i]]+w[i]) 其中 v v v是