寒假ACM集训复习总结Day3-helman

这一天学的是贪心算法和暴力枚举

感觉比第一天的思维题还简单,也许是因为全部列出来是人的普遍想法吧

那就放几个经典例题吧

HDU - 2037

一道经典的看电视的问题,给出一系列节目的开始结束时间,算出你最多能看几部

思路是要对每个节目的结束时间从小到大排序,每次选择结束时间早的不和上一个节目冲突的节目

#include <bits/stdc++.h>
using namespace std;
struct tv{
    int begin;
    int end;
}t[101];
bool cmp(tv &a,tv &b){
    return a.end<b.end;
}
int main(){
    freopen("1.in","r",stdin);
    int n;
    while(cin>>n&&n){
        for(int i=0;i<n;i++)
            cin>>t[i].begin>>t[i].end;
        sort(t+0,t+n,cmp);
        int ans=1,e=t[0].end,b;
        for(int i=1;i<n;i++){
            b=t[i].begin;
            if(b<e)continue;
            ans++;
            e=t[i].end;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

又是一道经典例题,数塔问题,这里分成两个方法求解

HDU - 2084

第一种是通过分析后,我们采用动态分析的思想,从下到上,每次都选择下一行里最大的数相加,代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+7;
int main(){
    freopen("1.in","r",stdin);
    int c,n;
    int m[101][101];
    cin>>c;
    while(c--){
        cin>>n;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
                cin>>m[i][j];
        for(int i=n-1;i>=1;i--){
            for(int j=1;j<=n-1;j++)
                m[i][j]+=max(m[i+1][j],m[i+1][j+1]);
        }
        cout<<m[1][1]<<endl;
    }
    return 0;
}

第二种方法是从上到下,这种做法缺点是求每一个数时都要从塔顶开始加起,十分费时,解决方法就是建立一个数组来储存算好的数的值,这种方法叫做记忆化搜索,也叫备忘录

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+7;
int m[101][101],b[101][101];
int n;
int bd(int i,int j){
    if(m[i][j])return m[i][j];
    if(i>n||j>n)return 0;
    m[i][j]=b[i][j]+max(bd(i+1,j),bd(i+1,j+1));
    return m[i][j];
}
int main(){
    //freopen("1.in","r",stdin);
    int c;
    cin>>c;
    while(c--){
        memset(m,0,sizeof(m));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=i;j++)
                scanf("%d",&b[i][j]);
        cout<<bd(1,1)<<endl;
    }
    return 0;
}

 

posted @ 2019-03-03 11:43  helman78  阅读(130)  评论(0编辑  收藏  举报