NEUQACM预备队必做题第四周

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值