0、听课笔记
\(IOI\)原题,世界高中生信息学竞赛
需要进省队,进国家队,每年有4人代表中国参加\(IOI\)竞赛。
这道题如此简单,是因为是上世纪\(IOI\)的原题。
1、dfs
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int a[N][N];
int f[N][N];
int n;
int dfs(int x,int y){
int sum=0;
//左下方,x+1,y
//右下方,x+1,y+1
if(x==n+1) return sum;
return sum=max(dfs(x+1,y),dfs(x+1,y+1))+a[x][y];
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++)
cin >> a[i][j];
}
cout<<dfs(1,1)<<endl;
return 0;
}
结果:简单样例通过
本题数据范围
\(1≤n≤500, −10000≤\)三角形中的整数\(≤10000\)
因为爆搜的时间复杂度是 \(2^{n-1}\),所以\(500\)的话就是\(2^{499}\),肯定是\(TLE\)了!需要想办法优化。
2、记忆化搜索
#include <iostream>
#include <cstring>
using namespace std;
const int N = 510;
int a[N][N];
int f[N][N];
int n;
int dp[N][N];
int dfs(int x,int y){
//如果算过,就直接返回
if(dp[x][y]!=0x3f3f3f3f) return dp[x][y];
int sum=0;
//左下方,x+1,y
//右下方,x+1,y+1
if(x==n+1) return sum;
dp[x+1][y]=dfs(x+1,y);
dp[x+1][y+1]=dfs(x+1,y+1);
return sum=max(dp[x+1][y],dp[x+1][y+1])+a[x][y];
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++)
cin >> a[i][j];
}
for(int i=1;i<=n;i++)
memset(dp,0x3f,sizeof dp);
cout<<dfs(1,1)<<endl;
return 0;
}
3、DP 动态规划
动态规划
(1)状态表示
\(f[i][j]\)
集合:从底向上走到\((i,j)\)所有路线的集合
属性:\(max\)
(2)状态计算
\(f[i][j]=max(f[i+1][j],f[i+1][j+1])+a[i][j]\)
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int f[N][N];
int main() {
//优化输入
ios::sync_with_stdio(false);
int n;
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= i; j++)
cin >> f[i][j];
//dp
for (int i = n - 1; i >= 1; i--)
for (int j = 1; j <= i; j++)
f[i][j] += max(f[i + 1][j], f[i + 1][j + 1]);
//输出结果
cout << f[1][1] << endl;
return 0;
}