模拟类型算法(1)

洛谷 1327数列排序

题目链接
给定一个无序数列,应该交换几次就能变成一个有序数列,首先要保存这个两个一样的无序数列,然后一个数组给它排序,两个数组进行比较,如果数组元素不一致,就交换次数加一,进行调换,调换的时候,我们要知道跟数组里的哪个元素进行调换,所以我们还需要知道在有序数组里在这个位置的元素的下标,所以我们需要一个STL容器map,这跟普通数组有什么区别呢,map比普通数组的容量更大,数组不能超过1e9,但是map可以。

#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=1e5+5;
map<int,int>F;
int a[N],b[N];
int n,m,ans;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i],F[a[i]]=i;
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
        if(a[i]!=b[i]){
            ans++;
            int x=F[b[i]];
            F[a[i]]=x;
            a[x]=a[i];
        }
    printf("%d",ans);
}

洛谷 1308统计单词数

题目链接
注意点:
1、字符串有空格,怎么输入,用gets函数;
2、怎么不区分大小写,要么全变成大写,要么全变成小写;
3、怎么匹配,这里要求的是匹配单词,所以从有空格的地方的前一个单词开始匹配,不要从有空格的后面,因为这样第一个单词就能匹配上的时候会忽略。

#include<iostream>
#include<cstring>
using namespace std;
#include <cctype>
#include <cstdio>

void strlower (char *a) {//手写函数,将大写字母转换成小写字母
	for(int i = 0; a[i]; i ++ ) {
		if(isupper(a[i])) a[i] = tolower(a[i]);//isupper是判断是否是大写字母的系统函数,tolower是将其转换成小写字母的函数
	}
}
char a[11];
char s[100001];
int ans;
int main(){
	gets(a);
	gets(s); 
	int len=strlen(a);
	strcat(a," "); 
    strcat(s," ");//在ab后各加一个" ",减小配对的难度 
	strlower(a);
	strlower(s);
	int i, n=0, j, ss=0, k, rec;
	for(i=0;s[i]!='\0';i++){
		if (s[i] == ' ') {
            ans=1;
            for (j = n,k = 0; j <= i, a[k] != '\0'; j++, k++) {
                if(s[j] == a[k]) {
                    ans*=1;//用s来记录各个位能否对应,如果结果是1就正确,一位不对s就变成0 
                } else {
                     ans*=0;
                }
            }
            if (ans == 1) {
                ss++; //如果每次都对就增加符合的次数 
            }
            if (ss == 1 && ans==1) {
                rec = n; //记录第一次符合的位数 
            }
            n=i;
            n++;
        }
	}
	if(!ss){
		cout<<-1<<endl;return 0;
	}
	cout<<ss<<" "<<rec<<endl;
	return 0;
}

洛谷 1328生活大爆炸版石头剪刀布

题目链接

注意:
1、得分表的到来,罚分记为0,平分记为0,得分记为1,阴影部分由非阴影部分得来,如甲出蜥蜴人,乙出石头,可由甲出石头,乙出蜥蜴人得出,甲对乙的结果是输,为什么罚分为0,不为-1,因为我们要计算的是他们两人的得分。
2、为什么要取余,因为当n大于aa和bb的时候,我们要得到的数组下标不能大于aa和bb。

#include<iostream>
using namespace std;
int n, aa, bb, a[300], b[300], numa, numb;
int book[5][5] = {{0,0,1,1,0},{1,0,0,1,0},{0,1,0,0,1},{0,0,1,0,1},{1,1,0,0,0}}; //得分表的处理 
int main(){
	cin>>n>>aa>>bb;
	for(int i=0;i<aa;i++){
		cin>>a[i];
	}
	for(int i=0;i<bb;i++){
		cin>>b[i];
	}
	 for(int i = 0; i < n; i++)
    {
        numa += book[a[i % aa]][b[i % bb]]; //周期循环 
        numb += book[b[i % bb]][a[i % aa]];
    }
    cout << numa << " " << numb << endl;
	return 0;
}

洛谷 P1334 瑞瑞的木板 P1090 合并果子
瑞瑞的木板
合并果子

这里需要讲讲什么是优先队列
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。

在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。

首先要包含头文件#include, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。

优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

和队列基本操作相同:

top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。

当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
一般是:

//升序队列,小顶堆
priority_queue <int,vector<int>,greater<int> > q;
//降序队列,大顶堆
priority_queue <int,vector<int>,less<int> >q;

//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

这上面两个题目所用的代码一样,都是用到了升序队列,跟普通队列不同的就是优先队列对队列里的元素进行了排序。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
priority_queue<ll,vector<ll>,greater<ll> > a;//这里直接调用优先队列
int main(){
    long long ans=0,n,t;//ans注意要开long long,不然会爆
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&t);
        a.push(t);
    }
    for(int i=1;i<=n-1;i++){
        int c,d;
        c=a.top();
        //cout<<c<<" ";
        a.pop();
        d=a.top();
        //cout<<d<<endl;
        a.pop();//每次取最小的两个数
        ans+=c+d;//加上能量
        a.push(c+d);
}//和合并果子一样
    printf("%lld",ans);
    return 0;
}

这周就整理了这些啦,希望对看到的你有所帮助!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值