数字三角形模型
AcWing 1015. 摘花生
#include <iostream>
using namespace std;
const int N = 110;
int w[N][N];
int f[N][N];
//f[i][j] 表示从(1,1)到(i,j)最多能够摘到的花生数;
[int main()
{
int T;
cin >> T;
while(T--)
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) cin >> w[i][j];
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
//从两个方向过来
f[i][j] = max(f[i-1][j], f[i][j - 1]) + w[i][j];
cout << f[n][m] << endl;
}
return 0;
}
#include <iostream>
using namespace std;
const int N = 110, INF = 1e9;
int g[N][N], f[N][N];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) cin >> g[i][j];
//是求最小值 需要处理边界问题
//!!!处理边界很重要
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(i == 1 && j == 1) f[i][j] = g[i][j];
else
{
f[i][j] = INF;
//从左边过来
if(i > 1) f[i][j] = min(f[i][j], f[i - 1][j] + g[i][j]);
//从上边过来
if(j > 1) f[i][j] = min(f[i][j], f[i][j - 1] + g[i][j]);
}
cout << f[n][n] << endl;
return 0;
}
#include <iostream>
using namespace std;
const int N = 15;
int g[N][N], f[N + N][N][N];
int a, b, c;
//f[k][i1][i2] 表示所有从(1,1),(1,1)分别走到(i1, k - i1),(i2, k - i2)的路径的最大值
//其中k = i1 + j1 = i2 + j2
int main()
{
int n;
cin >> n;
while(cin >> a >> b >> c, a || b || c) g[a][b] = c;
//从(1, 1)开始
for(int k = 2; k <= n + n; k++)
for(int i1 = 1; i1 <= n; i1++)
for(int i2 = 1; i2 <= n; i2++)
{
int j1 = k - i1, j2 = k - i2;
if(j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n)
{
int t = g[i1][j1];
if(i1 != i2) t += g[i2][j2];
int &x = f[k][i1][i2]; //引用 一变都跟着变
//下下 下右 右下 右右
//向右走时是j在变 i不变
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
x = max(x, f[k - 1][i1 - 1][i2] + t);
x = max(x, f[k - 1][i1][i2 - 1] + t);
x = max(x, f[k - 1][i1][i2] + t);
}
}
cout << f[n + n][n][n] << endl;
return 0;
}
#include <iostream>
using namespace std;
const int N = 55;
int g[N][N], f[N + N][N][N];
int a, b, c;
//f[k][i1][i2] 表示所有从(1,1),(1,1)分别走到(i1, k - i1),(i2, k - i2)的路径的最大值
//k = i1 + j1 = i2 + j2
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
cin >> g[i][j];
//从(1, 1)开始
for(int k = 2; k <= n + m; k++)
//因为有 1 <= x1 <= n 1 <= k - x1 <= m
for(int i1 = max(1, k - m); i1 <= min(k - 1, n); i1++)
for(int i2 = max(1, k - m); i2 <= min(k - 1, n); i2++)
{
int t = g[i1][k - i1];
if(i1 != i2) t += g[i2][k - i2];
int &x = f[k][i1][i2]; //引用 一变都跟着变
//下下 下右 右下 右右
//向右走时是j在变 i不变
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
x = max(x, f[k - 1][i1 - 1][i2] + t);
x = max(x, f[k - 1][i1][i2 - 1] + t);
x = max(x, f[k - 1][i1][i2] + t);
}
cout << f[n + m][n][n] << endl;
return 0;
}
最长上升子序列模型
AcWing 1017. 怪盗基德的滑翔翼
#include <iostream>
using namespace std;
const int N = 110;
int a[N], f[N]; //f[i] 表示到从0到i的递增长度
//求最长上升子序列 或者是最长下降子序列
int main()
{
int T;
cin >> T;
while(T--)
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
int res = 0;
for(int i = 1; i <= n; i++)
{
f[i] = 1;
for(int j = 1; j < i; j++)
if(a[i] > a[j])
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
}
for(int i = n; i > 0; i--)
{
f[i] = 1;
for(int j = n; j > i; j--)
if(a[i] > a[j])
f[i] = max(f[i], f[j] + 1); //一直算以f[i]结尾的长度
res = max(res, f[i]);
}
cout << res << endl;
}
return 0;
}
#include <iostream>
using namespace std;
const int N = 1010;
int a[N], f[N], g[N];
//即是求先上升后下降的最大长度
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++)
{
f[i] = 1;
for(int j = 1; j < i; j++)
if(a[i] > a[j])
f[i] = max(f[i], f[j] + 1);
}
for(int i = n; i > 0; i--)
{
g[i] = 1;
for(int j = n; j > i; j--)
if(a[i] > a[j])
g[i] = max(g[i], g[j] + 1);
}
int res = 0;
for(int i = 1; i <= n; i++) res = max(res, f[i] + g[i] - 1);
//减1是因为重复计算了两次
cout << res << endl;
return 0;
}
//代码和上题基本上一致 题目本意也是基本一致
#include <iostream>
using namespace std;
const int N = 110;
int a[N], f[N], g[N];
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++)
{
f[i] = 1;
for(int j = 1; j < i; j++)
if(a[i] > a[j])
f[i] = max(f[i], f[j] + 1);
}
for(int i = n; i; i--)
{
g[i] = 1;
for(int j = n; j > i; j--)
if(a[i] > a[j])
g[i] = max(g[i], g[j] + 1);
}
int res = 0;
for(int i = 1; i <= n; i++) res = max(res, f[i] + g[i] - 1);
cout << n - res << endl;
return 0;
}
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int N = 5010;
int f[N], n;
PII q[N];
int main()
{
cin >> n;
for(int i = 0; i < n; i++) cin >> q[i].first >> q[i].second;
sort(q, q + n); //需要排序 注意下标问题
int res = 0;
for(int i = 0; i < n; i++)
{
f[i] = 1;
for(int j = 0; j < i; j++)
if(q[i].second > q[j].second)
f[i] = max(f[i], f[j] + 1);
res = max(res, f[i]);
}
cout << res << endl;
return 0;
}
#include <iostream>
using namespace std;
const int N = 1010;
int a[N], f[N];
//注意状态表示和状态计算
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
int res = 0;;
for(int i = 1; i <= n; i++)
{
f[i] = a[i];
for(int j = 1; j < i; j++)
if(a[i] > a[j])
{
f[i] = max(f[i], f[j] + a[i]);
}
res = max(res, f[i]);
}
cout << res << endl;
return 0;
}