动态规划习题代码题解
最长上升子序列
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ )
cin >> a[i];
vector<int> dp(n + 1, 1);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j < i; j ++ )
if (a[i] > a[j])
dp[i] = max(dp[i], dp[j] + 1);
int maxx = 0;
for (int i = 1; i <= n; i ++ ) maxx = max(maxx, dp[i]);
cout << maxx << endl;
return 0;
}
P1048 [NOIP 2005 普及组] 采药
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T, M;
cin >> T >> M;
vector<int> a(M + 1), b(M + 1);
for (int i = 1; i <= M; i ++ ) cin >> a[i] >> b[i];
vector<vector<int>> dp(M + 1, vector<int> (T + 1, 0));
for (int i = 1; i <= M; i ++ )
for (int j = 1; j <= T; j ++ )
{
dp[i][j] = dp[i - 1][j];
if (a[i] <= j)
{
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - a[i]] + b[i]);
}
}
int ans = 0;
for (int i = 1; i <= T; i ++ )
{
ans = max(ans, dp[M][i]);
}
cout << ans << endl;
return 0;
}
P1060 [NOIP 2006 普及组] 开心的金明
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n, m;
cin >> m >> n;
vector<long long> v(n + 1), w(n + 1);
vector<vector<long long>> dp(n + 1, vector<long long> (m + 1));
for (int i = 1; i <= n; i ++ )
{
long long a, b;
cin >> a >> b;
v[i] = a;
w[i] = a * b;
}
long long ans = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
dp[i][j] = dp[i - 1][j];
if (j >= v[i])
dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
ans = max(ans, dp[i][j]);
}
cout << ans << endl;
return 0;
}
P1002 [NOIP 2002 普及组] 过河卒
#include <bits/stdc++.h>
using namespace std;
int a[100][100];
long long dp[100][100];
int dx[8] = {1, 2, 2, 1, -1, -2, -2, -1}, dy[8] = {2, 1, -1, -2, -2, -1, 1, 2};
int main()
{
int n, m, c, d;
cin >> n >> m >> c >> d;
memset(a, 0, sizeof a);
a[c][d] = 1;
for (int i = 0; i < 8; i ++ )
{
int x = dx[i] + c, y = dy[i] + d;
// cout << x << " " << y << endl;
if (x >= 0 && x <= n && y >= 0 && y <= m) a[x][y] = 1;
}
memset(dp, 0, sizeof dp);
dp[0][0] = 1;
for (int i = 0; i <= n; i ++ )
{
for (int j = 0; j <= m; j ++ )
{
if (i) dp[i][j] += dp[i - 1][j];
if (j) dp[i][j] += dp[i][j - 1];
if (a[i][j]) dp[i][j] = 0;
// if (a[i][j]) cout << "h" << " ";
// else cout << dp[i][j] << " ";
}
// cout << endl;
}
cout << dp[n][m] << endl;
return 0;
}
P1806 跑步
#include <bits/stdc++.h>
using namespace std;
long long dp[510][510];
int main()
{
int n;
cin >> n;
dp[0][0] = 1;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= i; j ++ )
{
for (int k = 0; k < j; k ++ )
{
dp[i][j] += dp[i - j][k];
}
// cout << dp[i][j] << " ";
}
// cout << endl;
}
long long ans = 0;
for (int i = 1; i <= n; i ++ )
ans += dp[n][i];
cout << ans - 1 << endl;
return 0;
}
最长正方形
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N][N], dp[N][N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
cin >> a[i][j];
}
int ans = 0;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
if (a[i][j] == 1)
{
dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
}
ans = max(ans, dp[i][j]);
// cout << dp[i][j] << " ";
}
// cout << endl;
}
cout << ans << endl;
return 0;
}
P11248 [GESP202409 七级] 矩阵移动
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int dp[N][N][N];
void solve()
{
int n, m, x;
cin >> n >> m >> x;
vector<string> s(n + 1);
for (int i = 1; i <= n; i ++ ){
cin >> s[i];
s[i] = " " + s[i];
// cout << s[i] << endl;
}
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
for (int k = 0; k <= x; k ++ )
{
dp[i][j][k] = max(dp[i][j - 1][k], dp[i - 1][j][k]) + (s[i][j] == '1');
if (s[i][j] == '?' && k) dp[i][j][k] = max(dp[i][j][k], max(dp[i][j - 1][k - 1], dp[i - 1][j][k - 1]) + 1);
}
}
int mx = 0;
for (int i = 0; i <= x; i ++ )
mx = max(mx, dp[n][m][i]);
cout << mx << endl;
}
int main()
{
int t;
cin >> t;
while (t -- )
{
solve();
}
return 0;
}