littlehb

题目传送门

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;
}

分类:

技术点:

相关文章: