int largest1BorderedSquare(vector<vector<int>>& grid) {
int m = grid.size();
int n = grid[0].size();
// 动态规划法
vector<vector<int>> up(m + 1, vector<int>(n + 1, 0)); // (x,y)及上方连续1的个数
vector<vector<int>> left(m + 1, vector<int>(n + 1, 0)); // (x,y)及左方连续1的个数
// 递推公式
int res = 0;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (grid[i - 1][j - 1] == 1) {
up[i][j] = up[i - 1][j] + 1;
left[i][j] = left[i][j - 1] + 1;
// 设以(x,y)为正方形右下顶点的正方形边长为l
// 左下顶点(x - l + 1, y)
// 右上顶点(x, y - l + 1)
int l = min(left[i][j], up[i][j]);
while (up[i][j - l + 1] < l || left[i - l + 1][j] < l) {
l--;
}
res = max(res, l);
}
}
}
return res * res;
}
int minimumDeletions(string s) {
// 遇到b跳过,遇到a考虑删除 / 删除前方所有的b
int cnt_b = 0, res = 0;
for (auto c : s) {
if (c == 'a') res = min(res + 1, cnt_b);
else cnt_b++;
}
return res;
}
博弈问题
int stoneGameII(vector<int>& piles) {
int n = piles.size(), sum = 0;
// dp[i][j]: 剩余[i : len - 1],M = j时,先取的人能获得的最多石子数
vector<vector<int>>dp(n, vector<int>(n + 1, 0));
// 递推公式
for (int i = n - 1; i >= 0; --i) {
sum += piles[i];
for (int M = 1; M <= n; ++M) {
// 剩下的堆数能够直接全部取走,那么最优的情况就是剩下的石子总和
if (i + 2 * M >= n) {
dp[i][M] = sum;
}
// 剩下的堆数不能全部取走,那么最优情况就是让下一个人取的更少
else {
// 遍历所有可能的取值
for (int x = 1; x <= 2 * M; ++x) {
dp[i][M] = max(dp[i][M], sum - dp[i + x][max(x, M)]);
}
}
}
}
return dp[0][1];
}
二维DP
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<long long> nums(n);
for(int i = 0; i < n; ++i){
cin >> nums[i];
}
// dp[i][j]:取前i个数字,模k为j的最大数
vector<vector<long long>> dp(n+1, vector<long long>(k, 0));
for (int i = 0; i < k; i++) {
dp[0][i] = -1;
}
dp[0][0] = 0;
for(int i = 1; i <= n; ++i){
for(int j = 0; j < k; ++j){
long long temp = (j + k - nums[i - 1] % k) % k;
if (dp[i - 1][temp] != -1)
dp[i][j] = max(dp[i-1][j], dp[i - 1][temp] + nums[i - 1]);
else
dp[i][j] = dp[i-1][j];
}
}
if(dp[n][0]==0)
cout << -1 << endl;
else
cout << dp[n][0] << endl;;
}
树型DP
#include <iostream>
#include <vector>
using namespace std;
vector<int> color;
int dp[100001]={0}; //dp[i]!=0 表示这个位置需要上一个色 (一般是 [parent,son] 一组)
// dfs1: 研究能否成功上色
void dfs1(vector<vector<int>> &mp, int pre, int cur)
{
for(int i = 0;i < mp[cur].size(); i++)
{
int child = mp[cur][i];
if(child == pre)
continue; //跳过环路
dfs1(mp, cur, child);
if(!dp[cur] && !dp[child])
{
dp[cur] = cur;
dp[child] = cur; //全部调整为index数值
}
}
}
// dfs2: 调整上色: 遍历过程中记录当前的dp[]与parent是否相同即可
void dfs2(vector<vector<int>> &mp, int pre, int cur){
for(int i = 0;i < mp[cur].size(); i++){
int child = mp[cur][i];
if(child == pre)
continue; //跳过环路
if(dp[cur] == dp[child]){
color[child] = color[cur];
}
else{
color[child] = !color[cur];
}
dfs2(mp, cur, child);
}
}
int main() {
int n;
cin >> n;
color.resize(n + 1);
vector<vector<int>> mp(n+1, vector<int>());
for(int i = 1; i <= n-1; ++i){
int x,y;
cin >> x >> y;
mp[x].push_back(y);
mp[y].push_back(x);
}
dfs1(mp, -1, 1);
for(int i = 1; i <= n; ++i){
if(dp[i] <= 0){
cout << -1 << endl;
return 0;
}
}
dfs2(mp, -1, 1);
string res;
for(int i = 1; i <= n; ++i){
res.push_back(color[i] == 0 ? 'R' : 'B');
}
cout << res << endl;
}
#include <algorithm>
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
int dfs(vector<vector<int>> &mp, vector<int> &val, vector<int> &dp, int root){
if(mp[root].empty()){
dp[root] = val[root];
return val[root];
}
if(mp[root].size() == 1){
// 最好子节点为负不如不选
int best_child = max(dfs(mp, val, dp, mp[root][0]), 0);
int cur_best = val[root] + best_child;
dp[root] = cur_best;
return cur_best;
}
else{
int best_child_l = max(dfs(mp, val, dp, mp[root][0]), 0);
int best_child_r = max(dfs(mp, val, dp, mp[root][1]), 0);
int cur_best = val[root] + max(best_child_l, best_child_r);
dp[root] = val[root] + best_child_l + best_child_r;
return cur_best;
}
}
int main() {
int n;
cin >> n;
vector<int> val(n+1);
vector<int> dp(n+1, INT_MIN);
for(int i = 1; i <= n ; ++i){
cin >> val[i];
}
vector<vector<int>> mp(n+1, vector<int>());
for(int i = 1; i <= n ; ++i){
int x;
cin >> x;
mp[x].push_back(i);
}
dfs(mp, val, dp, 1);
cout << *max_element(dp.begin(), dp.end()) << endl;
}