pB 地鐵跑酷
Subtask 1 $M=1$
這個Subtask基本上是送分給大家,一排數字加起來就過了。
Subtask 2
令$dp[i][j][0/1]$表示前進了$i$單位,且現在正在第$j$條鐵軌上,$0/1$代表是否用過磁鐵,所能獲得最多的金幣數量。可以看出轉移式式這樣:
$dp[i][j][0]=max(dp[i-1][j-1][0],dp[i-1][j][0],dp[i-1][j+1][0])+w[i][j]$
$dp[i][j][1]=max(max(dp[i-1][j-1][0],dp[i-1][j][0],dp[i-1][j+1][0])+\Sigma_{k=1}^{M}w[i][k],$
$max(dp[i-1][j-1][1],dp[i-1][j][1],dp[i-1][j+1][1])+w[i][j])$
好好實作就可以AC了。
AC code:
```cpp=1
#include<bits/stdc++.h>
using namespace std;
#define jizz ios_base::sync_with_stdio(false);cin.tie(NULL);
const int MAXN=1E5+1;
int coin[MAXN][22], sum[MAXN], dp[MAXN][21][2];
int main(){ jizz
int n,m;
cin>>n>>m;
for(int j=1;j<=m;j++){
for(int i=1;i<=n;i++){
cin>>coin[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
sum[i]+=coin[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j][0]=max(dp[i-1][j-1][0],max(dp[i-1][j][0],dp[i-1][j+1][0]))+coin[i][j];
dp[i][j][1]=max(max(dp[i-1][j-1][0],max(dp[i-1][j][0],dp[i-1][j+1][0]))+sum[i],
max(dp[i-1][j-1][1],max(dp[i-1][j][1],dp[i-1][j+1][1]))+coin[i][j]);
}
}
int ans=0;
for(int i=1;i<=m;i++){
ans=max(ans,dp[n][i][1]);
}
cout<<ans<<"\n";
return 0;
}
```
pE 寶可夢養成日記
Subtask 1
BJ4
Subtask 2
基本上是Greedy,把(血量-攻擊力)由大到小排好後,取前$b$大使用第二種藥水就過了(當然要是正的)。
Subtask 3
搞不好可以爆搜之類的,不過我不會。
Subtask 4、5
這裡就要用到第二個Greedy,你會知道最好的做法永遠是對同一隻寶可夢用第一種藥水。所以最終做法就是枚舉對每一隻寶可夢使用所有第一種藥水的結果。時間複雜度為$O(NlogN)$。
AC code:
```cpp=1
#include<bits/stdc++.h>
using namespace std;
#define jizz ios_base::sync_with_stdio(false);cin.tie(NULL);
#define int long long
typedef pair<int,int> pii;
#define F first
#define S second
const int MAXN=2E5+1;
pii poke[MAXN];
bool cmp(pii p, pii q){
return p.F-p.S>q.F-q.S;
}
int getmax(pii p){
return p.F>p.S?p.F:p.S;
}
signed main(){ jizz
int n,a,b;
cin>>n>>a>>b;
b=min(n,b);
for(int i=0;i<n;i++){
cin>>poke[i].F>>poke[i].S;
}
sort(poke, poke+n, cmp);
int ans, res=0;
for(int i=0;i<n;i++){
if(i<b) res+=getmax(poke[i]);
else res+=poke[i].S;
}
ans=res;
if(b>0){
int mul=(1<<a);
for(int i=0;i<n;i++){
if(i<b){
ans=max(ans,res-getmax(poke[i])+poke[i].F*mul);
} else{
ans=max(ans,res-poke[i].S-getmax(poke[b-1])+poke[i].F*mul+poke[b-1].S);
}
}
}
cout<<ans<<"\n";
return 0;
}
```