第一次写博客(正式性的)
以前多多少少写过一点点东西,但是大都是写乱七八糟的东西,也没有坚持下去。现在不一样了,(我是一个有工作的人),为了那些热爱学习的学生们,我应该写点东西了,为了他们更好得学习与复习的资料,以后就要坚持更新博客了。
题目列表
POJ 3278 POJ 2442 HDU 1870 HDU 1022 HDU 1237 UVA 673 HDU 1509
进入正题
第一题
首先,来看这道题目,典型的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;
}