AtCoder Educational DP Contest 刷题记录Ⅰ
刷题背景1
我有女朋友了,在酒吧认识的。说起来很梦幻 感觉是双向一见倾心 一眼在人海中看见彼此的。真的很爱,当时情况很特殊不能长话短说 因为全是细节,要不这样吧 今天肯德基疯狂星期四 给我点个套餐我说出全部过程。
刷题背景2
为什么我要学信竞
我认为:
原因其一,信竞学术氛围严谨,勤勤恳恳,能打好知识体系的地基;
原因其二,信竞大佬众多,能引发选手疯狂的思考;
原因其三,信竞很关心选手,务实地在生活学习上帮助我处理问题、解答疑惑。
总结下来一句话:垦得基,疯狂兴起思,为我务实。
A - Frog 1
原题链接:A - Frog 1
分析
橙题调不过,我是**/(ㄒoㄒ)/~~
注意边界!!!
状态
我们设表示跳到第i个台阶的最小代价。
转移
答案
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int dp[N], h[N], n;
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n;for (int i = 1; i <= n; i++){cin >> h[i];dp[i] = 1e18;}dp[1] = 0;for (int i = 2; i <= n; i++){dp[i] = min(dp[i], dp[i - 1] + abs(h[i] - h[i - 1]));if (i >= 3){dp[i] = min(dp[i], dp[i - 2] + abs(h[i] - h[i - 2]));}}cout << dp[n];return 0;
}
B - Frog 2
原题链接:B - Frog 2
分析
秒了!同样卡一下边界,十分轻松!!!
状态
我们设表示跳到第i个台阶的最小代价。
转移
答案
正解
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int dp[N], h[N], n, k;
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> k;for (int i = 1; i <= n; i++){cin >> h[i];dp[i] = 0x3f3f3f3f;}dp[1] = 0;if (k > n){for (int i = 1; i <= n; i++){for (int j = 1; j <= i; j++){dp[i] = min(dp[i], dp[j] + abs(h[i] - h[j]));}}cout << dp[n];return 0;}for (int i = 1; i <= k; i++){for (int j = 1; j <= i; j++){dp[i] = min(dp[i], dp[j] + abs(h[i] - h[j]));}}for (int i = k + 1; i <= n; i++){for (int j = i - k; j <= i; j++){dp[i] = min(dp[i], dp[j] + abs(h[i] - h[j]));}}cout << dp[n];return 0;
}
C - Vacation
原题链接:C - Vacation
分析
又秒了!!!
状态
设表示第i天,强制
的最大快乐值
转移
答案
正解
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int dp[N][3];
int a[N], b[N], c[N];
int n;
int main(){cin >> n;for (int i = 1; i <= n; i++){dp[i][0] = dp[i][1] = dp[i][2] = 0xc0c0c0c0c0;cin >> a[i] >> b[i] >> c[i];}dp[1][0] = a[1];dp[1][1] = b[1];dp[1][2] = c[1];for (int i = 2; i <= n; i++){dp[i][0] = max(dp[i - 1][1], dp[i - 1][2]) + a[i];dp[i][1] = max(dp[i - 1][0], dp[i - 1][2]) + b[i];dp[i][2] = max(dp[i - 1][0], dp[i - 1][1]) + c[i];}cout << max({dp[n][0], dp[n][1], dp[n][2]});
}
D - Knapsack 1
原题链接:D - Knapsack 1
分析
标准的背包板子。
啥,过不了/(ㄒoㄒ)/~~
状态
设表示最多使用i的体积可以获得的最大价值
转移
答案
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 105, W = 100005;
int n, V;
int w[N], v[N];
int dp[W];
signed main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> V;for (int i = 1; i <= n; i++){cin >> w[i] >> v[i];}for (int i = 1; i <= n; i++){for (int j = V; j >= w[i]; j--){dp[j] = max(dp[j], dp[j - w[i]] + v[i]);}}cout << dp[V];
}
E - Knapsack 2
原题链接:E - Knapsack 2
分析
居然是维度转化吗?AT果然超模。
乍一看似乎和上题没区别,但是开dp数组是就应该意识到问题了,W太大了,会MLE+TLE。
那么,考虑维度转化。
状态
设表示价值为i的最小体积
转移
答案
满足的最大的i
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 105, M = 100005;
int n, W, w[N], v[N], sum;
int dp[M];
signed main(){cin >> n >> W;for (int i = 1; i <= n; i++){cin >> w[i] >> v[i];sum += v[i];}memset(dp, 0x3f, sizeof(dp));dp[0] = 0;for (int i = 1; i <= n; i++){for (int j = sum; j >= v[i]; j--){dp[j] = min(dp[j], dp[j - v[i]] + w[i]);}}int ans = 0;for (int i = 1; i <= sum; i++){if (dp[i] <= W){ans = i;}}cout << ans;
}
F - LCS
原题链接:F - LCS
分析
难点不在于长度 ,而在于保留答案,就需要被LCS板子了。
正解
#include <bits/stdc++.h>
using namespace std;
const int N = 3005;
int dp[N][N];
string s1, s2;
char ans[N];
int main(){cin >> s1 >> s2;int n = s1.length();int m = s2.length();s1 = " " + s1;s2 = " " + s2; for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);if (s1[i] == s2[j]){dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);}}}int i = n, j = m;while (dp[i][j] > 0){if (s1[i] == s2[j]){ans[dp[i][j]] = s1[i];i--;j--;}else{if (dp[i][j] == dp[i - 1][j])i--;elsej--;}}cout << ans + 1;
}
G - Longest Path
原题链接:G - Longest Path
分析
小心出度为0即可。
正解
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m, x, y;
bool vis[N];
int dp[N];
vector<int> e[N];
void dfs(int u) {if (vis[u]) return;vis[u] = true;if (e[u].empty()) {dp[u] = 0;return;}dp[u] = -1;for (auto v : e[u]) {dfs(v);dp[u] = max(dp[u], dp[v] + 1);}
}
int main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m;for (int i = 1; i <= m; i++){cin >> x >> y;e[x].push_back(y);}int ans = 0;for (int i = 1; i <= n; i++){dfs(i);ans = max(ans, dp[i]);}cout << ans;return 0;
}