算法学习

119 阅读4分钟

第一次写博客(正式性的)

以前多多少少写过一点点东西,但是大都是写乱七八糟的东西,也没有坚持下去。现在不一样了,(我是一个有工作的人),为了那些热爱学习的学生们,我应该写点东西了,为了他们更好得学习与复习的资料,以后就要坚持更新博客了。

题目列表

POJ 3278 POJ 2442 HDU 1870 HDU 1022 HDU 1237 UVA 673 HDU 1509

题目位于Vjudge备用地址

进入正题

第一题

BFS基础题目 首先,来看这道题目,典型的BFS模板题,属于超纲题目 ,我还没有给你们讲到BFS,但是不妨碍大佬们写出来,手动膜。 因为咱们还没学到,所以我先贴代码,后续补上题解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
struct node {
    int x; // 位置
    int step; // 行走次数
}now,nex; // 当前为位置,下次位置
int n,m;
int vis[200005]; // 标记,防止越界
int bfs(int n) {
    queue<node>q; // 队列是万能的
    now.x=n;
    now.step=0;
    vis[now.x]=1;
    q.push(now); // 初始地点信息压队列
    while(!q.empty()) {
        now =q.front();
        q.pop();
        if(now.x==m) // 判断是否可以结束了
            return now.step;
        for(int i=1; i<=3; i++) { // 三种行走方式
            if(i==1)
                nex.x=now.x+1;
            if(i==2)
                nex.x=now.x-1;
            if(i==3)
                nex.x=now.x*2;
            if(nex.x<0||nex.x>200005||vis[nex.x])continue; // 不符合的情况
            vis[nex.x]=1;
            nex.step=now.step+1;
            q.push(nex);
        }
    }
    return -1;
}
int main() {
    scanf("%d %d",&n,&m);
    memset(vis,0,sizeof(vis));
    int ans=bfs(n);
    printf("%d\n",ans);
    return 0;
}

第二题

在这里插入图片描述 题目大意: T组测试数据, m个序列,每个序列n个元素 从每一个序列中选择一个数字,组成一个含有n个元素的序列,使得组成的序列和最小。 【分析】: 我们先搞出来一个从大到小排序的优先队列,队列里面只放n个元素,保证放入的n个元素都是最小的,之后取出队列中的所有元素,求和便是答案,那么这道题就退化成为何动态维护队列(优先队列,以下简称队列 )了。 首先,将m行序列都按照从小到大的顺序排序。 将第一行序列里面的元素放入队列,然后取出,动态比较每一行元素中的某一个和下列行的元素值之和比较。

#include<iostream>
#include<cstdio>
#include<map>
#include<queue>
#include<algorithm>
#define ll long long
//#include<bits/stdc++.h>
using namespace std;
inline int in() {
    char ch;
    int a=0;
    while(!(((ch=getchar())>='0')&&(ch<='9')));  //利用getchar读入,速度快。
    a*=10;
    a+=ch-'0';
    while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';  //而后用ASCII码转为int 类型
    return a;
}
inline void out(int a) {
    if(a>=10)out(a/10);
    putchar(a%10+'0');
}
int num[105][2005],cun[2005];

void change(priority_queue<int>&p,int m) {
	
    for(int i = 0 ; i < m ; i++) {
        cun[i] = p.top();
        p.pop();
    }
}

int main() {
    int t;
    t=in();
    while(t--) {
        priority_queue<int>p;
        int n,m;
        n=in(),m=in();
        for(int i=0; i<n; i++) {
            for(int j=0; j<m; j++) {
                num[i][j]=in();
            }
            sort(num[i],num[i]+m);
        }
        for(int i=0; i<m; i++)
            p.push(num[0][i]);
        for(int i = 1 ; i < n ; i++) {
        	
        	change(p,m); // 此时队列为空 
        	
            for(int j = 0 ; j < m ; j++) {
                for(int k = m-1 ; k >= 0 ; k--) {
                    if(j == 0)
                        p.push( num[i][j]+cun[k] ); 
						// j == 0 ,这个判断会执行一个完整循环,队列中存入了m个元素 
						// 相当于第一列中最小的元素和第二列所有求和 
                    else {
                    	// 此时队列中已经有了 m 个元素,只需要剔除较大值,就能留下较小值 
                        if( num[i][j] + cun[k] < p.top() ) {
                        	
                            p.pop();
                            p.push(num[i][j]+cun[k]);
                        } else break; // 出现一个大于,直接过掉,因为数组有序。 
                    }
                }
            }
        }
        
        change(p,m);
        out(cun[m-1]);
        for(int j = m-2 ; j >= 0 ; j--) {
            printf(" ");out(cun[j]);
        }
        puts("");
    }
    return 0;
}

第三题

在这里插入图片描述 最简单的一道题,因为题目保证输入合法。所以就从栈退化成思维了,我们只需要统计B前面有几个没有被匹配上的‘(’就可以了。

#include <iostream>
#include <stack>
using namespace std;
stack<int> a;
int main(){
    char b;
    int sum=0;
	while(cin>>b){
		a.push(b);
		if(a.top()=='(') sum++;
		else if(a.top()==')') sum--;
		else{
			cout<<sum<<endl;
		} 
	}    
    return 0;
}

第四题

在这里插入图片描述 在这里插入图片描述 题目大意:给一个入栈序列,给一个出栈序列,判断出栈序列是否合法,如果合法,输出入栈出栈顺序。 【分析】:当入栈字符与出栈字符相匹配的时候,即可出栈,不匹配的时候就一直入栈,直到入栈序列结束。如果最后栈为空,即合法,不为空即不合法。此时我们引入一个vis数组,记录出入站顺序。

#include<bits/stdc++.h>
using namespace std;
char a[110],b[110];
int main() {
    int n;
    while(~scanf("%d %s %s",&n,a,b)) {
        stack<char> st;
        int i,j,kai;// i 控制入栈序列,j 控制出栈序列,kai 控制 vis 状态序列
        i=j=kai=0;
        int vis[110] = {0};
        while(n--) {
            st.push(a[i++]); // 入栈 
            vis[kai++]=1; // 标记入栈 
            while(!st.empty()) {
                if(st.top()==b[j]) { // 入栈字符与出栈字符相等 
                    st.pop();
                    j++; // 出栈序列右移 
                    vis[kai++]=2; // 标记出栈 
                } else break; // 不会符合出栈条件 
            }
        }
        if(st.empty()) { // 匹配成功 
            printf("Yes.\n");
            for(i=0; i<kai; i++) {
                if(vis[i]==1) printf("in\n");
                else if(vis[i]==2) printf("out\n");
            }
            printf("FINISH\n");
        } else {// 匹配失败
            printf("No.\n");
            printf("FINISH\n");
        }
    }
    return 0;
}

第五题

在这里插入图片描述

第六题

在这里插入图片描述 题目大意:经典括号匹配问题。 【分析】:左括号入栈,右括号如等于栈顶元素则出栈,不等于匹配失败

#include<cstdio>
#include<queue>
#include<algorithm>
#include<iostream>
#include<stack>
#include<string>
#include<cstring>
using namespace std;

char trans(char a)
{
	if(a==')') return '(';
	if(a==']') return '[';
	return ' ';  
}

int main()
{
	int n;
	cin>>n;
	getchar();
	while(n--)
	{
		stack<char> s;
		string str;
		getline(cin,str); // 使用 getline 规避空串烦恼
		int len=str.size();
		for(int i=0;i<len;++i)
		{
			if(s.empty()||s.top()!=trans(str[i])) s.push(str[i]);
			else s.pop();
		} 
		if(s.empty()) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
} 

第七题

在这里插入图片描述 在这里插入图片描述 题目大意+【分析】:典型的优先队列问题,不过需要重载排序规则。 给定对个字符串,如果是 GET 则获取队列中的值,如果是 PUT 则压入队列, 对于入队和出队操作,输出是否合法或者出队的值。

#include<cstdio>
#include<queue>
#include<algorithm>
#include<iostream>
#include<stack>
#include<string>
#include<cstring>
using namespace std;

struct node{
	string name;
	int num,data,rank;
	friend bool operator < (const node &a,const node b){ // 重载运算符
		return a.rank==b.rank?a.num>b.num:a.rank>b.rank;
	} 
};

priority_queue<node> pq;

int main()
{
	string str;int i=0;
	while(cin>>str)
	{
		if(str[0]=='G')
		{
			if(pq.empty()) cout<<"EMPTY QUEUE!"<<endl;
			else{
				cout<<pq.top().name<<" "<<pq.top().data<<endl;
				pq.pop();
			}
		}
		else{
			node t;
			cin>>t.name>>t.data>>t.rank;
			t.num=++i;
			pq.push(t);
		}
	}
	return 0;
} 

到此,第一场比赛的题解+代码就写完了,题目不难,但也需要思考思考才能写出来。望各位在以后的学习中能够脚踏实地,勤奋刻苦。在下半年的CSP中再创辉煌。