线性动态规划3
P1541 [NOIP 2010 提高组] 乌龟棋
做法1:记忆化搜索
#include<bits/stdc++.h>
using namespace std;
const int N = 360;
int a[N], b[5], dp[55][55][55][55];
int n, m;
int dfs(int pos){int sum = 0;if(pos == n)return a[n];if(dp[b[1]][b[2]][b[3]][b[4]])return dp[b[1]][b[2]][b[3]][b[4]];for(int i = 1; i <= 4; i++){if(b[i] == 0)continue;b[i]--;sum = max(sum, dfs(pos +i));b[i]++;} sum += a[pos];dp[b[1]][b[2]][b[3]][b[4]] = sum;return sum;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >> m;for(int i = 1; i <= n; i++)cin >> a[i];for(int i = 1; i <= m; i++){int x; cin >> x;b[x]++;}cout << dfs(1) << endl; return 0;
}
做法2:动态规划
由二维到四维写
#include<bits/stdc++.h>
using namespace std;
int a[360], b[5];
int dp[45][45][45][45];void solve(){int n, m; cin >> n >> m;for(int i = 1; i <= n; i++)cin >> a[i];for(int i = 1; i <= m; i++){int x; cin >> x;b[x]++;}dp[0][0][0][0] = a[1];for(int x1 = 0; x1 <= b[1]; x1++){for(int x2 = 0; x2 <= b[2]; x2++){for(int x3 = 0; x3 <= b[3]; x3++){for(int x4 = 0; x4 <= b[4]; x4++){int z = a[1 + x1 + x2 * 2 + x3 * 3 + x4 * 4];if(x1 != 0)dp[x1][x2][x3][x4] = max(dp[x1][x2][x3][x4], dp[x1 - 1][x2][x3][x4] + z);if(x2 != 0)dp[x1][x2][x3][x4] = max(dp[x1][x2][x3][x4], dp[x1][x2 - 1][x3][x4] + z);if(x3 != 0)dp[x1][x2][x3][x4] = max(dp[x1][x2][x3][x4], dp[x1][x2][x3 - 1][x4] + z);if(x4 != 0)dp[x1][x2][x3][x4] = max(dp[x1][x2][x3][x4], dp[x1][x2][x3][x4 - 1] + z);}}}}cout << dp[b[1]][b[2]][b[3]][b[4]] << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
P4310 绝世好题
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int dp[35][N];
int a[N], b[35];
void solve(){int n; cin >> n;for(int i = 1; i <= n; i++)cin >> a[i];for(int i = 1; i <= 31; i++)b[i] = 1 << (i - 1);for(int i = 1; i <= n; i++){int maxx = 0;for(int j = 1; j <= 31; j++){if(a[i] & b[j])maxx = max(maxx, dp[j][i - 1]);}maxx++;for(int j = 1; j <= 31; j++){if(a[i] & b[j])dp[j][i] = maxx;else dp[j][i] = dp[j][i - 1];}}int ans = 0;for(int i = 1; i <= 31; i++)ans = max(ans, dp[i][n]);cout << ans << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
优化1:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int dp[35];
int a[N], b[35];
void solve(){int n; cin >> n;for(int i = 1; i <= n; i++)cin >> a[i];for(int i = 1; i <= 31; i++)b[i] = 1 << (i - 1);for(int i = 1; i <= n; i++){int maxx = 0;for(int j = 1; j <= 31; j++){if(a[i] & b[j])maxx = max(maxx, dp[j]);}maxx++;for(int j = 1; j <= 31; j++){if(a[i] & b[j])dp[j] = maxx;else dp[j] = dp[j];}}int ans = 0;for(int i = 1; i <= 31; i++)ans = max(ans, dp[i]);cout << ans << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
优化2:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int dp[35];
int a[N], b[35];
void solve(){int n; cin >> n;for(int i = 1; i <= n; i++)cin >> a[i];for(int i = 1; i <= 31; i++)b[i] = 1 << (i - 1);for(int i = 1; i <= n; i++){int maxx = 0;for(int j = 1; b[j] <= a[i]; j++){if(a[i] & b[j])maxx = max(maxx, dp[j]);}maxx++;for(int j = 1; b[j] <= a[i]; j++){if(a[i] & b[j])dp[j] = maxx;else dp[j] = dp[j];}}int ans = 0;for(int i = 1; i <= 31; i++)ans = max(ans, dp[i]);cout << ans << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}