B3637
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,i,j;
cin>>n;
vector<vector<int> > v(n,vector<int> (2));
for(i=0;i<n;i++){
cin>>v[i][0];
v[i][1]=1;
}
i=1;
while(i<n){
for(j=0;j<i;j++){
if(v[j][0]<v[i][0]&&(v[j][1]+1)>v[i][1]) v[i][1]=v[j][1]+1;
}
i++;
}
int max=0;
for(i=0;i<n;i++){
if(v[i][1]>max) max=v[i][1];
}
cout<<max;
}
思路: 易知对于只有一个数的数列来说包含该数的最长上升序列长度为1,那么每新增一个数,遍历它前面所有小于它的数,将包含其的最长上升序列长度最大的加上1得到包含新数的最长上升序列长度,若前面没有小于它的数则记为1。最后遍历所有结果输出最大值。
P1115:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,i,j;
cin>>n;
vector<vector<int> > v(n,vector<int> (2));
for(i=0;i<n;i++){
cin>>v[i][0];
v[i][1]=0;
}
v[0][1]=max(0,v[0][0]);
i=1;
while(i<n){
v[i][1]=max(v[i-1][1]+v[i][0],0);
i++;
}
int max=0;
for(i=0;i<n;i++){
if(v[i][1]>max) max=v[i][1];
}
if(max==0){
max=-10001;
for(i=0;i<n;i++){
if(v[i][0]>max) max=v[i][0];
}
}
cout<<max;
}
思路:取第一个数与0的较大者为a(1),对之后的第i个数,取其与a(i-1)的和与0的较大者为a(i)。遍历完成后找到a(n)的最大值。如果大于0则输出,如果等于0则输出原数列中的最大者。
P8707:
#include <bits/stdc++.h>
using namespace std;
int main(){
int x,y,i,j;
cin>>x>>y;
vector<vector<int> > v(x,vector<int> (y));
for(i=0;i<x;i++) v[i][0]=1;
for(j=1;j<y;j++) v[0][j]=1;
for(i=1;i<x;i++){
for(j=1;j<y;j++){
if(i%2==1&&j%2==1){
v[i][j]=0;
}
else{
v[i][j]=v[i-1][j]+v[i][j-1];
}
}
}
cout<<v[x-1][y-1];
}
思路:用二维数组构造一个坐标系,将左边界和上边界的值记为1,然后按从左到右,从上到下的顺序遍历二维数组,将不可进入的点的值记为0,其他点的值为左边一点的值加上上面一点的值。最后输出目标点的值。
P1216
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,i,j;
cin>>n;
vector<vector<int> > v(n,vector<int>(n));
for(i=0;i<n;i++){
for(j=0;j<=i;j++) cin>>v[i][j];
}
for(i=n-1;i>0;i--){
for(j=0;j<i;j++){
v[i-1][j]+=max(v[i][j],v[i][j+1]);
}
}
cout<<v[0][0];
}
思路:从底层开始向上遍历,将每一对兄弟的较大值加到其双亲上,最后输出根结点的值。
P1020
#include <bits/stdc++.h>
using namespace std;
int x;
void f(vector<int> *v){
if(v->empty()||x>v->back()) v->push_back(x);
else *(lower_bound(v->begin(),v->end(),x)) = x;
}
void g(vector<int> *v){
if(v->empty()||x<=v->back()) v->push_back(x);
else *(lower_bound(v->rbegin(),v->rend(),x)-1) = x;
}
int main(){
vector<int> v1,v2;
while(scanf("%d",&x)!=EOF){
f(&v1);
g(&v2);
}
cout<<v2.size()<<endl<<v1.size();
}
思路:最多能拦截的导弹数为即最长不上升序列长度,最少需要的系统数则为最长上升序列长度。开两个长度可变数组,从第一个数开始遍历数据,如果数组a为空或该数不大于数组a尾端的数,将其加入到数组a尾端,否则找到数组a中第一个小于该数的成员将其替换;如果数组b为空或该数大于数组b尾端的数,将其加入到数组a尾端,否则找到数组a中第一个不小于该数的成员将其替换。最后输出数组a和b的长度。
s