3.25

蓝桥杯:历年试题倒是比较适合打基础。

开始一天一年真题,大约一个星期,恰好去上大检验一下,有什么变化。一定要完成啊 ,否则。。。还谈什么其他的。

还可以看一下这样的效果如何,是否需要改进。计划还是要写一下,更容易落实。主要不要有侥幸心理。

下周是正规课对应的习题,具体到时候确定大概计划。

//引用,真他的厉害:在我的团队里,聚集了一批这样的天才人物。目前Face++ 团队成员共60 个左右,其中超过80% 来自清华,80% 以上是工程师,30 多个人至少曾获得过一项世界级编程比赛奖项,得过国际奥林匹克竞赛金牌的有7 个,大多数成员有海外留学和专业机构工作的背景。

//大二上学期或大三上学期参加ACM区域赛,放再这里警醒自己。

2017

1.迷宫

dfs+暴力,主要考察代码熟练度。每一个遍历一下,因为要计数(在没有规律的前提下,当然是要遍历了),然后找临界,环是不行的,到达边的时候就代表可以出去。

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
string a[10];//要会使用string,使用 

bool vis[12][12];//尽量用bool数组 
bool dfs(int i,int j){
	if(vis[i][j]) return false ;
	if(i<0||i>9||j<0||j>9) return true;
	vis[i][j]=1;
	switch(a[i][j]){
		case 'U':
			return dfs(i+1,j);
		case 'D'://要用单引号 
			return dfs(i-1,j);
		case 'E':
			return dfs(i,j-1);
		case 'R':
			return dfs(i,j+1);
		default:
		return false; 
	}
	
	
}
int main(){
	a[0]="UDDLUULRUL";//双引号 
	a[1]="UURLLLRRRU";//使用char的话不可以用这样的初始化 
	a[2]="RRUURLDLRD";
	a[3]="RUDDDDUUUU";
	a[4]="URUDLLRRUU";
	a[5]="DURLRLDLRL";
	a[6]="ULLURLLRDU";
	a[7]="RDLULLRDDD";
	a[8]="UUDDUDUDLL";
	a[9]="ULRDLUURRR";//初始化可以一行行的
	int ans=0;
	for(int i=0;i<10;i++){
		for(int j=0;j<10;j++){
			memset(vis,0,sizeof(vis));
			if(dfs(i,j)){
				ans++;
			}
			
			
		}
	} 
	cout<<ans<<endl;
	return 0;
}

答案为10

2.跳蚱蜢

由于排列有限,至少经过多少次的话一般是BFS,模拟还是比较难的。代码答案为40(忘记对不对了

#include<iostream>
#include<cstdio>
#include<queue>
#include<set>
#include<cstring>
#include<algorithm>
using namespace std;
struct stateandlevel{
	char *state;
	int pos0,level;
	stateandlevel(char *ss,int lee,int poss):state(ss),level(lee),pos0(poss){}

};
struct cmp{//struct
	bool operator()(char *a,char *b){
		return strcmp(a,b)<0;
	}

};
queue<stateandlevel>q;
set<char*,cmp> allstate;
char *start={"012345678"};
char *target="087654321";
void swap(char *a,int pos,int pos0){
	char t=a[pos];
	a[pos]=a[pos0];
	a[pos0]=t;
}
void addnei(char *s,int pos,int newpos,int le){
	char *new_state=(char*)malloc(9*sizeof(char));
	strcpy(new_state,s);
	swap(new_state,pos,newpos);
	if(allstate.find(new_state)==allstate.end()){
		allstate.insert(new_state);
		q.push(stateandlevel(new_state,le+1,newpos));
	}
}
int main(){
	q.push(stateandlevel(start,0,0));
	while(!q.empty()){
		stateandlevel ans=q.front();
		char *state=ans.state;
		int le=ans.level;
		int pos=ans.pos0;
		if(strcmp(state,target)==0){
			cout<<le<<endl;
			return 0;
		}
		int new_pos=(pos-1+9)%9;
		addnei(state,pos,new_pos,le+1);
		new_pos=(pos-2+9)%9;
		addnei(state,pos,new_pos,le+1);
		 new_pos=(pos+1+9)%9;
		 addnei(state,pos,new_pos,le+1);
	new_pos=(pos+2+9)%9;
	addnei(state,pos,new_pos,le+1);
		q.pop();
	}
}

D:\xiaotingting\Untitled1.cpp|22|warning: deprecated conversion from string constant to 'char*'|
D:\xiaotingting\Untitled1.cpp|23|warning: deprecated conversion from string constant to 'char*'|
||=== Build finished: 0 errors, 2 warnings ===|
要会适当忽略错误

3.方格填数

答案为2686

要学会用check单独处理,然后对换后一个个再回溯 或者用全排列,也是一种常见题型。

#include<iostream>
#include<algorithm>
using namespace std;
int a[10]={0,1,2,3,4,5,6,7,8,9};

bool check(){
	if(abs(a[0]-a[1])==1||abs(a[0]-a[3])==1||abs(a[0]-a[4])==1||abs(a[0]-a[5])==1||abs(a[1]-a[2])==1||abs(a[1]-a[4])==1||abs(a[1]-a[5])==1||abs(a[1]-a[6])==1||abs(a[2]-a[5])==1||abs(a[2]-a[6])==1||
	abs(a[3]-a[4])==1||abs(a[3]-a[7])==1||abs(a[3]-a[8])==1||abs(a[4]-a[5])==1||abs(a[4]-a[7])==1||abs(a[4]-a[8])==1||abs(a[4]-a[9])==1||abs(a[5]-a[6])==1||abs(a[5]-a[8]==1)||abs(a[5]-a[9])==1||
	abs(a[6]-a[9])==1||abs(a[7]-a[8])==1||abs(a[8]-a[9])==1){//可枚举 
		return false;
	} 
	return true;
}
int ans;
void f(int k){
	if(k==10){
		if(check()){
			ans++;
		}
	}
	for(int i=k;i<=9;i++){//包括本身 
		int t=a[k];
		a[k]=a[i];
		a[i]=t;
		f(k+1);//递归 
		t=a[k];
		a[k]=a[i];
		a[i]=t;//回溯 
		
	}
	
} 
int main(){
	f(0);
	cout<<ans<<endl;
	return 0; 
} 

4.快速排序

#include<iostream>
#include<algorithm>
using namespace std;
void swap(int a[],int i,int j){
	int t=a[i];
	a[i]=a[j];
	a[j]=t;
	
}
int partition(int a[],int i,int j){
	int q=i; 
	int r=j+1;//后面会多减 
	int p=a[q]; //因为到后面i会变,所以 
	while(1){
		while(q<j&&a[++q]<p) ;//范围 ,不是q<r会死循环的 
		while(a[--r]>p) ;
		if(q>=r) break;//先后决定是否会重复换 
		swap(a,q,r);
		
		
	}
	swap(a,i,r);
	return r;
}
void quicksort(int a[],int i,int j){
	if(i<j)//i==j就没必要写了,容易不严谨 
{
	int p=partition(a,i,j);
	quicksort(a,i,p-1);
	quicksort(a,p+1,j);
}
	 
}
int main(){
	int a[8]={1,5,3,2,4,9,7,5};
	quicksort(a,0,7);
	for(int i=0;i<=7;i++){
		cout<<a[i]<<" ";
	}
	
	return 0;
	
}

是道填空题,但是自己写还是错了挺久的细节。快速排序为基础,而且涉及二指针和三指针等等变种,也需要了解。

5.字母组串

是递归题,同样也是填空题

#include<iostream>
#include<cstdio>
using namespace std;
int f(int a,int b,int c,int n){//组成多少个长度n的字符串 
	
	if(a<0||b<0||c<0) return 0 ;//先后 
	if(n==0) return 1;
	return f(a-1,b,c,n-1)+f(a,b-1,c,n-1)+f(a,b,c-1,n-1);//数量同时要减一 
	
}
int main (){
	cout<<f(1,1,1,2)<<endl;
	cout<<f(1,2,3,3)<<endl;
	return 0;
}

6.最大公共子串

#include<iostream>
#include<cstdio>
using namespace std;
#define N 256
int c[N][N];
int maxx;
int f(const char*a,const char *b){
	maxx=0;
	memset(c,0,sizeof(int)*N*N);
	int len1=strlen(a);
	int len2=strlen(b);
	for(int i=1;i<=len1;i++){
		for(int j=1;j<=len2;j++){
			if(a[i-1]==b[j-1]) {//注意初始化 
				c[i][j]=c[i-1][j-1]+1;
				if(maxx<c[i][j]){
					maxx=c[i][j];
				//	cout<<maxx<<endl;
				}
			}
		}
	}
	return maxx;
}
int main(){
	printf("%d\n",f("abefcd","becd"));
	return 0;
	
} 

简单的动态规划

可以超出

7.正则问题

主要是理解问题,还有就是代码的熟练度了

细节总是出错,事实证明,我做每一道题若不是有十足的把握,起码要有三个自己写的例子来检验

#include<iostream>
#include<cstdio>
using namespace std;
char a[100];
int temp; 
int m;//存储最大 
int pos;//位置变化 
int len; 
int f(){
	m=0;temp=0;//初始化 
	//int len=strlen(a);
	
	while(pos<len){
		if(a[pos]=='('){
		//	temp=0;
			pos++;
		//	cout<<temp<<endl;
			int poss=f();//
		//	cout<<poss<<endl;//属于临时变量 
			temp=temp+poss;
			//cout<<temp<<endl;
		
			
		}
		else if(a[pos]=='x'){
			//m++;
			temp++;
			pos++;
			
		}
		else if(a[pos]==')'){
			m=max(m,temp);
		//	cout<<m<<endl;
			temp=0;//注意要清零,否则会继续 
			pos++;
			return m;
			
		}
		else if(a[pos]=='|'){
			m=max(m,temp);
			temp=0;
			pos++;
			
			//m=max(m,)
		}
	}
	m=max(m,temp);
	return m;
}
int main(){
	scanf("%s",a);
	len=strlen(a); 
//	cout<<len<<endl;
	int  res=f();
	cout<<res<<endl;
	return 0; 
} 

错了很久的说。

8.包子凑数

要会适当推广,不是系数的最大公倍数不是1的话,凑不出来的就有INF个,然后再用背包思想去做。去凑

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6;
int a[maxn];
bool b[maxn];
int main(){
	int n;int g;
	cin>>n; 
	b[0]=true;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(i==1){
			g=a[i];
		}
		else {
			g=__gcd(g,a[i]);
		}
		
		for(int j=0;j<10000;j++){//有个公式可以估计范围,来确定答案 a*b-a-b
			if(b[j]){
				b[j+a[i]]=true;//无限个嘛,完全背包 
			}
			
		}
	
	}
	if(g!=1){
			cout<<"INF"<<endl;
			return 0;
		}
	int ans=0;
	for(int i=0;i<10000;i++){
		if(!b[i]){
			ans++;
		}
	}
	cout<<ans<<endl;
	return 0;
} 

数学公式的使用,类比于完全背包之类的

9.分巧克力

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+1;
int h[maxn];
int ll[maxn];
int main(){
	int n,k;
	cin>>n>>k;int ans=0;
	for(int i=1;i<=n;i++){
		cin>>h[i]>>ll[i];
		
	}
	int l=1;int r=100001;
	while(l<=r){
		int mid=(l+r)>>1;int cnt=0;
		for(int i=1;i<=n;i++){
			cnt+=(h[i]/mid)*(ll[i]/mid);
			
		}
		if(cnt>=k){
			l=mid+1;
			ans=mid;//可再加一个变量 
		}
		else { 
		r=mid-1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

二分,反正主要是我没基础的话,写对是件需要长时间练习的事。(而且由于是我

10.油漆面积

这道题目可以暴力过,一开始的话也许?//主要是要思维开阔些,冷静些

但是个线段树的扫面线+矩形的模板题

估计要和这题僵持很久了

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1e4+2;
bool p[maxn][maxn];
void paint(int x1,int y1,int x2,int y2){
	for(int i=x1;i<x2;i++){
		for(int j=y1;j<y2;j++){//
			p[i][j]=1;
		}
	}
}
int main(){
	int n;int x1,x2,y1,y2;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x1>>y1>>x2>>y2;
		paint(x1,y1,x2,y2);
		
	}
	int sum=0;
	for(int i=0;i<10001;i++){
		for(int j=0;j<10001;j++){
			if(p[i][j]){
				sum++;
			}
		} 
	}
	cout<<sum<<endl;
	return 0;
	
}

N堆石子排成一列,两两合并成一堆,只能相邻的合并。合并代价为两堆石子个数之和。总的代价为所有中间结果之和。

思路是: 本问题实际上就是哈夫曼编码,每次选择最小的两堆合并,合并的代价总和就是最终的最小代价,可以借助小根堆实现

首先这道题目特殊在于总的次数是一定的,那么每一次都选最小的话,虽然是在变化后的数组选的,但是依旧是原数组的第几大,若是分开来的话。

油漆面积

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4;
//写了很久依旧不对,好吧,留在这里,留待以后解决吧 
struct line{
	int x1,x2,h,f;//入边,出边 
	line(){}
	line(int x11,int x22,int hh,int ff):x1(x11),x2(x22),h(hh),f(ff){	}
	bool operator<(const line&l)const{
		return h<l.h;
	}
	
}lines[N]; 
int x[N<<1];//记录所有横坐标
 

struct segtree{
	int pl,pr,cnt,len;
	segtree():cnt(0),len(0){}
	segtree *lson,*rson;

};//
segtree *buildtree(int pl,int pr){
	segtree *t=new segtree();
	t->pl=pl;
	t->pr=pr;
	if(pl==pr) return t;
	int mid=(pl+pr)>>1;
	
	t->lson=buildtree(pl,mid);
	t->rson=buildtree(mid+1,pr);
	return t; 
	
}
void updatelength(segtree*ptree,int tl,int tr){
	if(ptree->cnt){
		ptree->len=x[tr]-x[tl-1];//
	}
	else if(tr==tl){
		ptree->len=0;
	}
	else {
		ptree->len=ptree->lson->len+ptree->rson->len;//负数 
	}
}
void update(segtree *t,int pl,int pr,int value){
	int tl=t->pl;
	int tr=t->pr;
	if(tl<=pl&&tr>=pr){
		t->cnt+=value;
		updatelength(t,pl,pr);
		return ;
	}
	int mid=(tl+tr)>>1;
	
//	if()
	if(pl<=mid){
		update(t->lson,pl,pr,value);
	}
	if(mid<pr) update(t->rson,pl,pr,value);//有相交的地方 
	updatelength(t,tl,tr);
//	rre 
}
int ans;
int main(){
	int n;
	cin>>n;
	int x1,y1,x2,y2;
	int index=0;
	for(int i=0;i<n;i++){
		
		cin>>x1>>y1>>x2>>y2;
		x[index]=x1;
		lines[index]=line(x1,x2,y1,1);index++;
		x[index]=x2;
		lines[index]=line(x1,x2,y2,-1);
		index++;
	}
	sort(x,x+index);
	sort(lines,lines+index);
	int x_end=unique(x,x+index)-x;
	segtree *root=buildtree(1,x_end);//末尾取不到 ,建树
	 
	
	for(int i=0;i<index;i++){
		int pl=lower_bound(x,x+x_end,lines[i].x1)-x;
		int pr=lower_bound(x,x+x_end,lines[i].x2)-x;//两次出现 
		update(root,pl+1,pr,lines[i].f);
		ans+=root->len*(lines[i+1].h-lines[i].h);
	}
	cout<<ans<<endl;
	return 0;
	 
	
} 

终于明白一拳打倒棉花上的感觉了。

还有到了第二天,根本没完成计划内的事,太失败了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值