P1
題敘
詳細題述
給一棵樹
每個點有點權
求每個邊至少一個點被選中的最小值
n,m <= 2e5 , a[i]<=100
思路
經典樹dp題, 秒了
程式碼
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
vector<int> adj[N];
int a[N];
int vis[N],dp[N][2];
void dfs(int u){
dp[u][1]+=a[u];
for(int v:adj[u]){
if(vis[v]) continue;
vis[v]=1;
dfs(v);
dp[u][1] += min(dp[v][0],dp[v][1]);
dp[u][0] += dp[v][1];
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
vis[1]=1;
dfs(1);
cout << min(dp[1][0],dp[1][1]) << '\n';
}P2
題敘
給一個n*m個格子
每個格子上下左右的街道會給一個值(-100~100)
只能走左右、下,不能重複走
問從任意起點
走到
任意終點的最大值
思路
跟之前的 勇者修練 很像,
總之就是一道經典的方格圖dp
我們先定義dp[i][j][0/1/2]為 走到i,j時最後從上往下/左往右/右往左 的最大值
首先因為不能往上走,所以我們一定是從上算下來,然後又不能重複走
所以同一列往左走的一定不會跟往右走的有關,反之亦然
我們只要從左掃一遍再從右掃一遍就可以了
詳細轉移可以看程式碼理解
程式碼
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+5;
int g[N][N][4];
// R,D,L,U
int dp[N][N][3];
int main(){
int n,m;
cin>>m>>n;
for(int i=1;i<=m;i++){
for(int j=1;j<n;j++){
int v;
cin>>v;
g[i][j][0] = g[i][j+1][2] = v;
}
}
for(int i=1;i<m;i++){
for(int j=1;j<=n;j++){
int v;
cin>>v;
g[i][j][1] = g[i+1][j][3] = v;
}
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
dp[i][j][0] = max({
dp[i-1][j][0]+g[i-1][j][1],
dp[i-1][j][1]+g[i-1][j][1],
dp[i-1][j][2]+g[i-1][j][1],
0
});
dp[i][j][1] = max({
dp[i][j-1][0]+g[i][j-1][0],
dp[i][j-1][1]+g[i][j-1][0],
0
});
}
for(int j=n;j>=1;j--){
dp[i][j][2] = max({
dp[i][j+1][0]+g[i][j+1][2],
dp[i][j+1][2]+g[i][j+1][2],
0
});
}
}
int ans = -1e9;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
ans = max({ans,dp[i][j][0],dp[i][j][1],dp[i][j][2]});
}
}
cout << ans << '\n';
}P3
題敘
詳細題述
給一個1~9的字串
再中間插入幾個+ 求 <m 的最大值跟方法數
|S| <=40 , m<=3e4
思路
uhhh因為前面兩題都是dp所以我這題完全沒想過dp
有想過折半枚舉但我不會寫
最後只寫了一般的枚舉,大概40分吧
程式碼
#include <bits/stdc++.h>
using namespace std;
string s;
int n,m;
int ans=0;
int cnt=0;
void rec(int idx,int cur){
if(idx==n){
if(cur>ans){
ans=cur;
cnt=1;
}
else if(cur==ans){
cnt++;
}
return;
}
int ccr=0;
for(int i=idx;i<n;i++){
ccr = ccr*10+(s[i]-'0');
if(cur+ccr>m) break;
rec(i+1,cur+ccr);
}
}
int main() {
ios::sync_with_stdio(0),cin.tie(0);
cin>>s>>m;
n = s.size();
rec(0,0);
cout << ans << '\n' << cnt << '\n';
}結尾
我都拿 AACPOJ 測試過了
拿了 255/300 分
希望APCS測資爛一點讓我能賽到250分((
等我11/13更新這裡ouob






