【题记】(启用前绝密)

目录

字符串二叉排序树

思路 

代码

判断栈的输出序列

​编辑

思路

代码

三元组实现对称矩阵相乘

 思路

Blah数集(优先队列)

Blah数集 

问题分析

暴力?

找找规律?

代码

优先队列

模板生成系统(CCF)

最大字典序

先决知识

问题分析

代码

判断有向图是否是简答无环图

六度分离(floyd)

求连通分量

最小生成树权值之和

 字符串镜像(栈)

KMP模板题

 火车购票(模拟or队列?)

数组模拟

队列

二叉树结点(二叉树)

哈夫曼带权路径

求后序序列

next数组求解

逆序输出中序序列

二叉树的遍历

计算水坑个数

これはBFSですか?be like迷宫问题?

 矩阵最长递增路径

上课

等待更暖和的一天

农场主喝水

帮助退休夫妻找路

判断是否是镜像二叉树


字符串二叉排序树

思路 

 很简单就是在传统二叉排序树的构建过程中略略修改:比较key的过程改为字符串的比较。

然后结点的数据形式变成字符串。最后再加上深度的求解。

直接

代码

#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=1000;
char str[N][N];

struct Node{
	char ch[N];
	Node *lchild,*rchild;
};
class BST{
	private:
		Node* root;
	public:
		void insertBST(Node* &bt,char *s);
		void inOrder(Node*bt);
		BST(char str[N][N],int length);
		Node* getRoot(){return root;}
		int getDepth(Node* bt);
		
};

BST::BST(char str[N][N],int length){
	root=NULL;
	for(int i=0;i<length;i++){
		insertBST(root,str[i]);
	}
	return;
}

void BST::insertBST(Node* &bt,char *s){
	if(bt==NULL){
		bt=new Node;
		int i,len=strlen(s);
		for(i=0;i<len;i++){
			bt->ch[i]=s[i];
		} 
		bt->ch[i]='\0';
		bt->lchild=NULL;
		bt->rchild=NULL; 
	}
	else{
		if(strcmp(s,bt->ch)<0) insertBST(bt->lchild,s);
		else insertBST(bt->rchild,s); 
	}
}

void BST::inOrder(Node* bt){
	if(bt==NULL) return;
	else{
		inOrder(bt->lchild);
		cout<<bt->ch<<" ";
		inOrder(bt->rchild);
	}
	return;
}

int BST::getDepth(Node* bt){
	if(bt->lchild==NULL&&bt->rchild==NULL) return 1;
	else{
		int l=0,r=0;
		if(bt->lchild!=NULL) l=getDepth(bt->lchild);
		if(bt->rchild!=NULL) r=getDepth(bt->rchild);
		return 1+max(l,r);
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>str[i];
	}
	BST bst(str,n);
	Node* root=bst.getRoot();
	bst.inOrder(root);
	cout<<bst.getDepth(root);
	return 0;
}

判断栈的输出序列

思路

这题可以看到之前写过的出栈合法性那题的影子。就是模拟,不赘述惹。

直接

代码

#include<iostream>
#include<string>
#include<stack>
using namespace std;
const int N=100;

int a[N],b[N];

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n;i++) cin>>b[i];
	int ans=0;
	stack<int> st;
	for(int i=0,k=0;i<n;i++){
		st.push(a[i]);
		while(!st.empty()&&st.top()==b[k]) k++,st.pop(),ans++;
		if(k==n){
			cout<<ans;return 0; 
		}
	}
	cout<<0;
	return 0;
}

已A!

三元组实现对称矩阵相乘

 思路

稀疏矩阵压缩那节就提到过,一直没写。今天稍稍写一下吧。

 注意是对称的!!

#include<iostream>
using namespace std;
const int N1=35;
const int N2=55;

//矩阵压缩之稀疏矩阵实现矩阵相乘。 
struct Tri{
	int x;
	int y;
	int w;
}; 

int n,num1,num2;
Tri tria[N2],trib[N2];

int getAW(int x,int y){
	for(int i=0;i<num1;i++){
		if(tria[i].x==x&&tria[i].y==y) return tria[i].w;
	}
	return 0;
}
int getBW(int x,int y){
	for(int i=0;i<num2;i++){
		if(trib[i].x==x&&trib[i].y==y) return trib[i].w;
	}
	return 0;
}

int main(){
	cin>>n;
	cin>>num1>>num2;
	for(int i=0;i<num1;i++) cin>>tria[i].x>>tria[i].y>>tria[i].w;
	for(int i=0;i<num2;i++) cin>>trib[i].x>>trib[i].y>>trib[i].w;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			int sum=0;
			for(int k=0;k<n;k++){
				int a=max(getAW(i,k),getAW(k,i)),b=max(getBW(k,j),getBW(j,k));
				sum+=a*b;
			}
			cout<<sum<<" ";
		}
		cout<<endl;
	}
	
}

Blah数集(优先队列)

Blah数集 

问题分析

暴力?

所谓万物皆可暴力(bushi),我们直接用循环把他前n个数存在一个数组里面然后排个序?

不会分析时间复杂度就很grass了。

(我自己的想法)

找找规律?

(这个图是不是蛮对称的hhhh,或许可以思考下去?) 

 以1为例。

1的2x+1这一路下去肯定是比3x+1下去要小。

而一次2x+1后的3x+1,与一次3x+1后的2x+1大小不确定,是不是需要比较一下嘞?

同时,先计算出来的数,也会比后面计算出来的数小。(不信你看图

以上是废话,我自己是这么think了一下的。

key

如果说暴力是全部找出来之后在排序,我们是不是可以想一下有什么可以边找边排序的?

单调栈?单调队列?

好的,已经想到了栈与队列了。

栈先进先出没什么关系,好像。

队列呢?二叉树层序遍历里面不是有一个使用队列的地方吗?

仔细想想好像有一点类似哦,层序遍历是使用一个队列,每输出一个根节点,就将他的左右子树入队。这样就可以保证根节点下一层左边部分的结点先输出了。

那这里呢?

我们是否可以把计算出来的数输出的同时,将他的后续入队,让他后续满足相对较小的先输出呢?

可是怎么区分“2x+1这一路”和“3x+1”?

对的,用两个队列,一个存放2x+1,一个存放3x+1。从起始的值开始入队,利用先进先出的性质。

这里我们就直接可以发现,两个队列是天然的单调队列了。

之前是相对较小,这下只需一步“相对”变“绝对”。

在每次要输出的时候,把两个队列的头头比较,输出那个较小的。

不知道这种带着思考的问题分析效果怎么样,反正我是蛮享受的。找个时间把单调队列的滑动窗口水一下hhhhh

现在应该就有思路了吧,用stl可以,数组模拟队列也可以。

代码

#include<iostream>
using namespace std;
const int N=5e6+10;

int a[N],b[N],h1,t1,h2,t2;

int main(){
	int num,n;
	while(cin>>num>>n){
		h1=1,t1=0,h2=1,t2=0;
		int i=0;
		while(i<n){
			i++;
			if(i==n) break;
			a[++t1]=num*2+1;
			b[++t2]=num*3+1;
			if(a[h1]>b[h2]) num=b[h2++];
			else if(a[h1]<b[h2]) num=a[h1++];
			else{
				num=a[h1++];
				h2++;
			}
		}
		cout<<num<<endl;		
	}
	return 0;
}

优先队列

#include<iostream>
#include<queue>
using namespace std;
int main(){
	int num,n;
	while(cin>>num>>n){
		priority_queue<int,vector<int>,greater<int> > c;
		int i=1;
		c.push(num);
		while(i<n){
			num=c.top();
			c.pop();
			while(!c.empty()&&c.top()==num) c.pop();
			c.push(num*2+1);
			c.push(num*3+1);
			i++;
		}
		cout<<c.top()<<endl;
	}
	return 0;
} 

模板生成系统(CCF)

 

与前端的梦幻联动!hhhhhh

 不会写,补正则表达式呜呜呜呜呜呜。

最大字典序

先决知识

字典序是什么  

字典序(dictionary order),又称 字母序(alphabetical order),原意是表示英文单词在字典中的先后顺序,在计算机领域中扩展成两个任意字符串的大小关系。

简言之 就是将两个字符串从左到右按照ASCII码比较大小,如果有一方大,他的字典序就大,相同的话继续比较,直到出现不同的字符或者最后两个串相等。

问题分析

我们当然要把最大的那个n放在第一个咯!

那第二个嘞?

首先我们知道,如果要出栈n这个最大的数,就需要先从头扫描,依次入栈,直到我们入栈出栈了n,对吧。

这时候栈可能已经有一定的基础了(栈中有一定的元素了)我们接着怎么比较?

这时候我们就有两种出栈的方式,1.直接弹栈顶  2.看一看后面有没有更大的数可以出栈。

所以

比较这时候的栈顶和后续数的最大那个。看看我们具体该走哪一个方案(我愿称之为试探)

第三个第四个就一次类推

代码

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
const int N=5e4+10;
int q[N];
int n;

vector<int> getResult(){
	stack<int> st;
	vector<int> ans;
	int i=0;
	while(q[i]!=n)
		st.push(q[i++]);
	ans.push_back(q[i++]);
	for(;i<n;){
		if(!st.empty()){
			int a=st.top(),b=q[i],index=b;
			for(int j=i;j<n;j++){
				if(q[j]>b) b=q[j],index=j; 
			}
			if(b>a) {
				while(i!=index) st.push(q[i++]);
				ans.push_back(q[i++]);	
			}
			else ans.push_back(a),st.pop();
		}
		else st.push(q[i++]);
	}
	while(!st.empty()) ans.push_back(st.top()),st.pop();
	return ans;
}


int main(){
	stack<int> st;
	cin>>n;
	for(int i=0;i<n;i++) cin>>q[i];
	
	vector<int> answer=getResult();
	for(int i=0;i<n;i++) cout<<answer[i]<<" ";
	return 0;
}

 嘿嘿~更新了一个高清图~ 

判断有向图是否是简答无环图

#include<iostream>
using namespace std;

const int N1=25,N2=210;
int numData[N1],arcData[N2][N2];
int num,edge;
int dist[N1],sum;

int main(){
	cin>>num>>edge;
	for(int i=0;i<edge;i++){
		int start,end;
		cin>>start>>end;
		arcData[start][end]=1;
		dist[end]+=1;
	}
	int visited[N1]={0};
	int m=num;
	while(m--){
		int index;
		for(int i=0;i<num;i++){
			if(dist[i]==0&&visited[i]==0) {
				index=i;
				visited[i]=1;
				break;
			}
		}
		for(int i=0;i<num;i++){
			if(arcData[index][i]==1&&dist[i]!=-1) dist[i]--;
		}
	}
	for(int i=0;i<num;i++) sum+=dist[i];
	if(sum==0) cout<<"true";
	else cout<<"false";
	return 0; 
}

这上面这个很明显地复杂了。

我改一改

#include<iostream>
using namespace std;

const int N1=25,N2=210;
int numData[N1],arcData[N2][N2];
int num,edge;
int dist[N1],sum;

int main(){
	cin>>num>>edge;
	for(int i=0;i<edge;i++){
		int start,end;
		cin>>start>>end;
		arcData[start][end]=1;
		dist[end]+=1;
	}
	int visited[N1]={0};
	int m=num;
	while(m--){
		int index,i=0;
		while(dist[i]!=0) i++;
		index=i;
		if(index==num){
			cout<<"false";
			return 0;
		}
		dist[index]=-1;
		for(int i=0;i<num;i++){
			if(arcData[index][i]==1&&dist[i]!=-1) dist[i]--;
		}
	}
	cout<<"true";
	return 0; 
}

 

六度分离(floyd)

 

这里的样例应该有一点问题,应该输出Yes.

夹带私货:大学的关系就是这么脆弱的嘛,害。 

#include<iostream>
using namespace std;
const int N=110;
const int MAXX=99999;

int A[N][N];
int num[N][N];
int n,m;

int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			A[i][j]=MAXX;
		}
	}
	for(int i=0;i<m;i++){
		int x,y;
		cin>>x>>y;
		A[x][y]=1;
		A[y][x]=1;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++) cout<<A[i][j]<<" ";
		cout<<endl;
	}
	
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			for(int k=0;k<n;k++){
				if(A[j][k]>A[j][i]+A[i][k]&&i!=j&&i!=k&&j!=k){
					A[j][k]=A[j][i]+A[i][k];
				}
			}
		}
	}
	
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++) cout<<A[i][j]<<" ";
		cout<<endl;
	} 
	
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(num[i][j]>7&&i!=j) {
				cout<<"No";
				return 0;
			}
		}
	}
	cout<<"Yes";
	return 0;
}

求连通分量

 邻接矩阵直接深搜。

#include<iostream>
using namespace std;

const int N=110;
int n,A[N][N];
int visited[N];

void DFS(int x){
	for(int i=0;i<n;i++){
		if(A[x][i]==1&&visited[i]==0){
			visited[i]=1;
			DFS(i);
		}
	}
}

int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++) cin>>A[i][j];
	}
	int ans=0;
	while(1){
		int sum;
		for(int i=0;i<n;i++) sum+=visited[i];
		if(sum==n) break;
		for(int i=0;i<n;i++){
			if(visited[i]==0){
				visited[i]=1;
				ans++;
				DFS(i);
			} 
		}
	}
	cout<<ans<<endl;
	return 0;
}

最小生成树权值之和

 最小生成树,我这里用的kruscal。

#include<iostream>
using namespace std;
const int N=25;

struct Edge{
	int from,to;
	int weight;
};

struct EdgeGraph{
	int vextex[N];
	Edge edge[N];
	int vexNum,edgeNum;
};


int getMin(int TL[],EdgeGraph eg){
	int el=0;
	int k=0;
	int sum=0;
	while(el<eg.vexNum-1){
		if(TL[eg.edge[k].from]!=TL[eg.edge[k].to]){
			int tmp=TL[eg.edge[k].to];
			sum+=eg.edge[k].weight;
			el++;
			for(int i=0;i<eg.vexNum;i++){
				if(tmp==TL[i]) TL[i]=TL[eg.edge[k].from];
			}
		}
		k++;
	}
	return sum;
}

int main(){
	EdgeGraph eg;
	cin>>eg.vexNum>>eg.edgeNum;
	for(int i=0;i<eg.vexNum;i++) eg.vextex[i]=i+1;
	//边插边排 
	cin>>eg.edge[0].from>>eg.edge[0].to>>eg.edge[0].weight; 
	for(int i=1;i<eg.edgeNum;i++){
		Edge g;
		cin>>g.from>>g.to>>g.weight;
		int j=0;
		for(;j<i;j++){
			if(eg.edge[j].weight>=g.weight){
				for(int k=i-1;k>=j;k--){
					eg.edge[k+1]=eg.edge[k];
				}
				break;
			}
		}
		eg.edge[j]=g;
	}
	int TL[N];
	for(int i=0;i<eg.vexNum;i++) TL[i]=eg.vextex[i];
	cout<<getMin(TL,eg)<<endl;
	return 0;
}

 字符串镜像(栈)

简单的栈的应用!

#include<iostream>
#include<stack>
using namespace std;
const int N=1e5+10;

char st[N];
int tt;

int main(){
	int ans=0;
	char ch;
	cin>>ch;
	while(ch!='@'){
		if(ch!='&'){
			if(tt&&st[tt]==ch) tt--,ans++;
			else st[++tt]=ch;
		}
		cin>>ch;
	}
	if(tt==0) cout<<ans;
	else cout<<"no";
	return 0;
} 

KMP模板题

 模板题,背住

//这是KMP 
#include<iostream>
#include<string>
using namespace std;
const int N1=35;
const int N2=15;

string a,b;

void getNext(string b,int *next){
	int i=0,j=-1;
	next[0]=-1;
	int len=b.size();
	while(i<len){
		if(j==-1||b[i]==b[j]){
			i++;
			j++;
			next[i]=j;
		}
		else j=next[j];
	}
}

bool KMP(string a,string b,int next[]){
	int i=0,j=0;
	int len=a.size();
	while(i<len){
		if(j==-1||a[i]==b[j]){
			i++;
			j++;
		}
		else j=next[j];
		if(j==b.size()) return true;
	}
	return false;
}

int main(){
	cin>>a;
	cin>>b;
	int next[N2]; 
	getNext(b,next);
	cout<<next[0];
	for(int i=1;i<b.size();i++) cout<<","<<next[i];
	cout<<endl;
	if(KMP(a,b,next)) cout<<"YES";
	else cout<<"NO";
	return 0;
}

 火车购票(模拟or队列?)

数组模拟

#include<iostream>
using namespace std;
const int N=110;

int inquire[N];
int seat[20][5]; 

int main(){
	int n;
	cin>>n;
	for(int i=0;i<n;i++) cin>>inquire[i];
	for(int i=0;i<n;i++){
		int num=inquire[i];
		for(int j=0;j<20;j++){
			int sum=0;
			for(int k=0;k<5;k++){
				sum+=seat[j][k];
			}
			if(num<=5-sum){ 
				int k=0;
				while(seat[j][k]!=0&&k<5) k++;
				while(num--){
					cout<<j*5+k+1<<" ";
					seat[j][k++]=1;
				}
				num=0;
				cout<<endl;
				break;
			}
		}
		if(num!=0){
			for(int j=1;j<=100;j++){
				if(num==0) break;
				int x=j/5;
				int y=j%5;
				if(y==0) x=x-1,y=4;
				else y=y-1;
				if(seat[x][y]==0){
					num--;
					seat[x][y]=1;
					cout<<j<<" ";
				}
			}
			cout<<endl;
		}
	}
	
} 

 队列怎么做嘞?

坐一个屁股在这。

更新啦

队列

其实也是模拟,只不过有了一个数据结构方便多了!!

#include<iostream>
#include<queue>
using namespace std;

const int N=21;
queue<int> mp[N];

int main(){
	int m;
	for(int i=0,j=1;i<20;i++){
		int cnt=5;
		while(cnt--){
			mp[i].push(j++);
		}
	} 
	cin>>m;
	for(int i=0;i<m;i++){
		int num;
		cin>>num;
		bool isLianxu=false; 
		for(int i=0;i<20;i++){
			//可以连续坐 
			if(mp[i].size()>=num){
				isLianxu=true;
				for(int j=0;j<num;j++){
					cout<<mp[i].front()<<" ";
					mp[i].pop();	
				}
				cout<<endl;
				break;
			}	
		}
		if(!isLianxu){
			bool isOk=false;
			for(int j=0;j<20&&num>0;j++){
				while(!mp[j].empty()&&num>0){
					cout<<mp[j].front()<<" ";
					mp[j].pop();
					num--;
				}
			}
			cout<<endl;
		}
	}
	return 0;
}

二叉树结点(二叉树)

 

这里的序列不完全,所以只能建树咯

#include<iostream>
using namespace std;

struct Node{
	char data;
	Node *l,*r;
};

Node* create(Node* bt){
	char ch;
	cin>>ch;
	if(ch=='#') return NULL;
	else{
		bt=new Node;
		bt->data=ch;
		bt->l=create(bt->l);
		bt->r=create(bt->r);
		return bt;
	}
}

int num;
void getNum(Node* bt){
	if(bt==NULL) return;
	if(bt->l==NULL&&bt->r==NULL) num++;
	if(bt->l!=NULL) getNum(bt->l);
	if(bt->r!=NULL) getNum(bt->r);
}

int main(){
	Node* root;
	root=create(root);
	getNum(root);
	cout<<num;
	return 0;
} 

哈夫曼带权路径

 之前有写过这一篇,放个链接http://t.csdn.cn/djJ3W

求后序序列

 之前有文章写过。

http://t.csdn.cn/ph9vG

#include<iostream>
#include<string> 
using namespace std;
string a,b;

void build(int l1,int r1,int l2,int r2){
	int m=b.find(a[l1]);
	if(m>l2) build(l1+1,l1+m-l2,l2,m-1); //左 
	if(m<r2) build(l1+m-l2+1,r1,m+1,r2); //右 
	cout<<a[l1];
	return;
}

int main(){
	cin>>a;
	cin>>b;
	int m=a.size()-1;
	build(0,m,0,m);
	return 0;
}

next数组求解

今天我们班一致赞同KMP的题最好做笑死。

大陈曦老师捞人----看破不说破

#include<iostream>
#include<string>
using namespace std;
const int N=110;

string a;
void getNext(string a,int *next){
	int i=0,j=-1,len=a.size();
	next[0]=-1;
	while(i<len){
		if(a[i]==a[j]||j==-1){
			i++;
			j++;
			next[i]=j;
		}
		else j=next[j];
	} 
}

int main(){
	cin>>a;
	int next[N];
	getNext(a,next);
	for(int i=0,len=a.size();i<len;i++) cout<<next[i]<<" ";
	return 0;
}

逆序输出中序序列

 好吧,又是不得不建树的一道题

挺简单的

#include<iostream>
#include<string> 
using namespace std;

string b;
int i;

struct Node{
	char data;
	Node *l,*r;
};

Node* create(Node* bt){
	char ch;
	cin>>ch;
	if(ch=='#') return NULL;
	bt=new Node;
	bt->data=ch;
	bt->l=create(bt->l);
	bt->r=create(bt->r);
	return bt;
}

void getInOrder(Node* bt){
	if(bt==NULL) return;
	getInOrder(bt->l);
	b[i++]=bt->data;
	getInOrder(bt->r);
	return;
}

int main(){
	Node* root;
	root=create(root);
	getInOrder(root);
	i--;
	while(i>=0){
		cout<<b[i--]<<" ";
	}
	return 0;
}

二叉树的遍历

#include<iostream>
#include<string> 
using namespace std;


struct Node{
	char data;
	Node *l,*r;
};

Node* create(Node* bt){
	char ch;
	cin>>ch;
	if(ch=='#') return NULL;
	bt=new Node;
	bt->data=ch;
	bt->l=create(bt->l);
	bt->r=create(bt->r);
	return bt;
}

void PreOrder(Node *bt){
	if(bt==NULL) return;
	cout<<bt->data;
	PreOrder(bt->l);
	PreOrder(bt->r);
	return;
}

void InOrder(Node* bt){
	if(bt==NULL) return;
	InOrder(bt->l);
	cout<<bt->data;
	InOrder(bt->r);
	return;
}

void PosOrder(Node* bt){
	if(bt==NULL) return;
	PosOrder(bt->l);
	PosOrder(bt->r);
	cout<<bt->data;
	return;
}

 

int main(){
	Node* root;
	root=create(root);
	PreOrder(root);
	cout<<endl;
	InOrder(root);
	cout<<endl;
	PosOrder(root);
	return 0;
}

样例是错的。之前还因为这玩意儿改了好久,以为是自己意识偏差。

计算水坑个数

 

これはBFSですか?be like迷宫问题?

 矩阵最长递增路径

上课

现在你总共有 N 门课需要选择,记为 0 到 N-1。

在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们,如: 0,1

给定课程总量,条件条数以及它们的先决条件,判断是否可能完成所有课程的学习?并判断两门课程是先修课程关系?

【输入形式】

第一行,输入:课程数N,课程之间的关系数M

第二行开始,输入M行,输入课程关系(若要学习课程1,需要先完成课程2)输入:课程1,课程2

继续输入两个课程编号c1,c2.

【输出形式】

第一行输出:是否可以完成课程(true/false)

第二行输出:c1是否是c2的先修课程(true/false),如果第一行为false,则不输出第二行。

【样例输入1】

4 4

1,0

2,0

3,1

3,2

3,0

【样例输出1】

true

true

【样例说明1】

总共有 4 门课程。要学习课程 0,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 3之后。这是可能的,因此第一行输出true。3是课程0的先修课程,因此第二行输出true。

【样例输入2】

2 2

1,0

0,1

1,0

【样例输出2】

false

【样例说明2】

总共有 2 门课程。学习课程0之前,你还应先完成课程1;并且学习课程1之前,你需要先完成课程0。这是不可能的,因此第一行输出true。第二行不输出。

简单拓扑拍序+判断无环图。

输入我用string可还行?

//拓扑排序 
#include<iostream>
using namespace std;
const int N=110;
int A[N][N],n,m; 
int c1,c2,k;
int paixu[N],du[N],visited[N];

int main(){
	cin>>n>>m;
	for(int i=0;i<m;i++){
		string a;
		cin>>a;
		A[a[0]-'0'][a[2]-'0']=1;
		du[a[2]-'0']++;
	}
	cin>>c1>>c2;
	for(int i=0;i<n;i++){
		int j;
		for(j=0;j<n;j++){
			if(du[j]==0&&visited[j]==0) break;
		}
		if(j==n){
			cout<<"false";
			return 0;
		} 
		paixu[k++]=j;
		visited[j]=1;
		for(int a=0;a<n;a++){
			if(A[j][a]==1&&du[a]>0) du[a]--;
		}
	}
	cout<<"true"<<endl;
	int index1,index2;
	for(int i=0;i<n;i++){
		if(paixu[i]==c1) index1=i;
		if(paixu[i]==c2) index2=i;
	}
	if(index1<index2){
		cout<<"true"<<endl;
	}
	else cout<<"false"<<endl;
	return 0;
} 

等待更暖和的一天

【问题描述】

给定每天的温度,求对于每一天需要等几天才可以等到更暖和的一天。如果该天之后不存在

更暖和的天气,则记为 0。天数不超过50天。

【输入形式】

输入是数组长度n和一个一维整数数组

【输出形式】

输出是同样长度的整数数组,表示对于每天需要等待多少天。

【样例输入】

8

73 74 75 71 69 72 76 73

【样例输出】

1 1 4 2 1 1 0 0

【样例说明】

第1天73°,第2天74°,第2天被超过,2-1=1;

第2天74°,第3天75°,第3天被超过,3-2=1;

第3天75°,第7天75°,第7天被超过,7-3=4;

第4天71°,第6天72°,第6天被超过,6-4=2;

...

...

最后两天没有被超越,输出都是0.

【提示】

创建一个单调递减的堆栈,堆栈中栈顶的温度低于栈底,当新出现的温度大于栈顶温度时,持续弹出,直到新温度小于栈顶温度。

实际建立堆栈时,可以压入温度数组的下标,通过下标读取对应的温度,也方便计算日期的差值。

单调栈可以解决问题。看不是很懂他在这里的提示。就先照自己的方式做咯。

其实就是一个求右边最靠近的较大值的下标问题。在加上一点距离的处理。

#include<iostream>

using namespace std;
const int N=110;
int stk[N],tt,n,num[N],ans[N];

int main(){
	cin>>n;
	int i;
	for(i=0;i<n;i++) cin>>num[i];
	for(i=n-1;i--;i>=0){
		while(tt&&num[stk[tt]]<=num[i]) tt--;
		if(!tt) ans[i]=0;
		else ans[i]=stk[tt];
		stk[++tt]=i;
	}
	for(int i=0;i<n;i++){
		if(ans[i]==0) cout<<0<<" ";
		else cout<<ans[i]-i<<" ";
	}
	return 0;
}

农场主喝水

【问题描述】
农场里有一些奶牛,作为食物的草料不够了。农场主需要去别的农场借草料。该地区有N (2 <= N <= 2,000) 个农场,农场名称用数字N标识,农场之间的道路是双向的,一共有M (1 <= M <= 10,000)条道路,单条长度不超过1,000,000,000里。有一些农场之间有多条道路相连。所有农场都有通路,连接到农场主的农场。农场主的农场是1号农场,他从自己的农场出发,去所有的农场借草料。
农场主需要在路上携带足够的水,假设马跑完一里路需要1盎司的水,在任意一个农场都可以补充水。那么他应该携带一个多大容量的水壶呢?

【输入形式】
第一行输入 N M
下面多行,每一行表示起点农场编号 终点农场编号 路径长度


【输出形式】
水壶的容量,单位为盎司


【样例输入】
3 3
1 2 12
2 3 123
1 3 50
【样例输出】
50
【样例说明】
【评分标准】

帮助退休夫妻找路

【问题描述】

张三和李四夫妇退休后,去国外风景秀美的H市买了一套房子准备安度晚年。住了一段时间后,他们对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车。请你写一个程序帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。

【输入形式】

第一行是公交车的总数N(0<=N<=10000);
第二行是张三的所在地start,目的地end;

接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
【输出形式】
如果张三能到达目的地,输出最短的时间;否则,输出“-1”。
【样例输入】
5
Leeds Edinburgh
Glasgow Edinburgh 70
Leeds Glasgow 10
Bristol Edinburgh 40
Leeds Edinburgh 65
Leeds Bristol 20
【样例输出】
60
提示: 时间最短的路径: Leeds -> Bristol ->Edinburgh ,虽然偶尔会迷路,但是因为有了你的帮助 张三和李四从此还是过上了幸福的生活。 

――全剧终――

判断是否是镜像二叉树

#include<iostream>
using namespace std;

struct Node{
	char data;
	Node *lchild,*rchild;
};

Node* create(Node* bt){
	char ch;
	cin>>ch;
	if(ch=='#') return NULL;
	bt=new Node;
	bt->data=ch;
	bt->lchild=create(bt->lchild);
	bt->rchild=create(bt->rchild);
	return bt;
} 

void preOrder(Node* bt){
	if(bt==NULL) return;
	else{
		cout<<bt->data;
		preOrder(bt->lchild);
		preOrder(bt->rchild);
		return;
	}
}

bool isSameTree(Node* l,Node* r){
	if(l==NULL&&r==NULL) return true;
	if(l==NULL||r==NULL) return false;
	if(l->data!=r->data) return false;
	return isSameTree(l->lchild,r->rchild)&&isSameTree(r->lchild,l->rchild);
}

bool isSymmetric(Node* bt){
	if(bt==NULL) return true;
	return isSameTree(bt->lchild,bt->rchild);
}



int main(){
	Node* root;
	root=create(root);
	preOrder(root);
	cout<<endl;
	if(isSymmetric(root)) cout<<"Yes";
	else cout<<"No";
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值