寒假ACM集训复习总结Day3-helman
这一天学的是贪心算法和暴力枚举
感觉比第一天的思维题还简单,也许是因为全部列出来是人的普遍想法吧
那就放几个经典例题吧
一道经典的看电视的问题,给出一系列节目的开始结束时间,算出你最多能看几部
思路是要对每个节目的结束时间从小到大排序,每次选择结束时间早的不和上一个节目冲突的节目
#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; }
又是一道经典例题,数塔问题,这里分成两个方法求解
第一种是通过分析后,我们采用动态分析的思想,从下到上,每次都选择下一行里最大的数相加,代码如下
#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; }