OJ提交地址:https://www.luogu.org/problemnew/show/P1540

http://noi.openjudge.cn/ch0112/07/

总时间限制: 1000ms 内存限制: 65536kB
描述

小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。

这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有M个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为N个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

输入
输入文件共2行。每行中两个数之间用一个空格隔开。
第一行为两个正整数M和N,代表内存容量和文章的长度。
第二行为N个非负整数,按照文章的顺序,每个数(大小不超过1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。

对于10%的数据有M = 1,N ≤ 5。
对于100%的数据有0 < M ≤ 100,0 < N ≤ 1000。

输出
共1行,包含一个整数,为软件需要查词典的次数。
样例输入
样例 #1:
3 7
1 2 1 5 4 4 1 样例 #2:
2 10
8 824 11 78 11 78 11 78 8 264
样例输出
样例 #1:
5 样例 #2:
6
提示
输入输出样例 1 说明:

整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:

空:内存初始状态为空。
1. 1:查找单词1并调入内存。
2. 1 2:查找单词2并调入内存。
3. 1 2:在内存中找到单词1。 
4. 1 2 5:查找单词5并调入内存。
5. 2 5 4:查找单词4并调入内存替代单词1。
6. 2 5 4:在内存中找到单词4。
7. 5 4 1:查找单词1并调入内存替代单词2。

共计查了5 次词典。

算法分析:

用队列先进先出的特性模拟内存存放单词;用一个一维数组标记某一个单词是否在于内存中以便快速确定是否需要查找词典。其余的基本就是纯粹模拟了。

有一点需要注意:若是使用循环队列,需要好好检查循环队列中元素个数的计算是否正确。

代码一:不使用循环队列,直接把队列定义得足够大

 #include<stdio.h>
#define maxQueueLength 1005
int main()
{
int M,N;
int que[maxQueueLength]={},check[]={}; // que[]是循环队列,用来模拟内存;check[i]==1表示i在内存中。
int ans=,begin,end,i,t;
scanf("%d%d",&M,&N); begin=end=;//初始化队列
for(i=;i<N;i++)
{
scanf("%d",&t);
if(check[t]==)//查找内存,发现内存中没有t存在
{
ans++;//查找字典的次数增加一次
//现在开始做单词放进内存的过程
if(end-begin<M)
{
que[end++]=t;
}
else //end-begin>=M
{
check[que[begin]]=;
begin++;
que[end++]=t;
}
check[t]=;//标记t已经在内存中
}
}
printf("%d\n",ans);
return ;
}

代码二:使用循环队列,节省一些队列空间

 #include<stdio.h>
#define maxQueueLength 105
int main()
{
int M,N;
int que[maxQueueLength]={},check[]={}; // que[]是循环队列,用来模拟内存;check[i]==1表示i在内存中。
int ans=,begin,end,i,t,count; scanf("%d%d",&M,&N); begin=end=;//初始化队列
for(i=;i<N;i++)
{
scanf("%d",&t);
if(check[t]==)//查找内存,发现内存中没有t存在
{
ans++;//查找字典的次数增加一次
//现在开始做单词放进内存的过程
if(end>=begin) count=end-begin;
else count=maxQueueLength-begin+end; if(count<M)
{
que[end++]=t;
if(end>=maxQueueLength) end=end%maxQueueLength;
}
else //end-begin>=M
{
check[que[begin]]=;
begin++;
que[end++]=t;
if(begin>=maxQueueLength)begin=begin%maxQueueLength;
if(end>=maxQueueLength)end=end%maxQueueLength;
}
check[t]=;//标记t已经在内存中
}
}
printf("%d\n",ans);
return ;
}

下面的代码也是用了循环队列,不过代码的可读性可能好一些哈哈哈

 #include <stdio.h>
#include <stdlib.h> int main()
{
int m,n;
int i;
int a[]={},count=;//a[]表示内存的空间。count记录当前内存中已经存有的单词个数
int firstIn=,lastIn=;//firstIn表示最早进入内存的单词在内存中的下标。lastIn表示下一个可以用于存储新单词的空闲空间的下标。
int b[]={};//b[i]==1表示i这个单词在内存中。否则表示i不在内存中。
int ans=,t; scanf("%d%d",&m,&n);
for(i=;i<n;i++)
{
scanf("%d",&t);//依次输入n个单词
if(b[t]==)//若单词t不在内存中
{
ans++;//需要查一次字典 //查完字典后需要把刚查的单词存入内存
if(count<m)//内存空间还有空闲
{
a[lastIn]=t;
b[t]=;
count++;
lastIn++;
lastIn=lastIn%m;
}
else//内存空间已经满了
{
//先腾空一个位置
b[a[firstIn]]=;
//a[firstIn]=0;
firstIn++;
firstIn=firstIn%m; //然后再把新单词放入内存
a[lastIn]=t;
b[t]=;
lastIn++;
lastIn=lastIn%m;
}
}
}
printf("%d\n",ans);
return ;
}

NOIP2010提高组 机器翻译的更多相关文章

  1. NOIP2010提高组 机器翻译 -SilverN

    /**/ #include<iostream> #include<cstdio> #include<cmath> #include<cstring> # ...

  2. [NOIP2010 提高组] 机器翻译

    问题描述 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换.对于每个英文单词,软件会先在内存中查 ...

  3. noip2010提高组题解

    NOIP2010提高组题解 T1:机器翻译 题目大意:顺序输入n个数,有一个队列容量为m,遇到未出现元素入队,求入队次数. AC做法:直接开1000的队列模拟过程. T2:乌龟棋 题目大意:有长度为n ...

  4. NOIP2010提高组真题部分整理(没有关押罪犯)

    目录 \(NOIP2010\)提高组真题部分整理 \(T1\)机器翻译: 题目背景: 题目描述: 输入输出格式: 输入输出样例: 说明: 题解: 代码: \(T2\)乌龟棋 题目背景: 题目描述: 输 ...

  5. NOIP2010提高组乌龟棋 -SilverN

    题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...

  6. 洛谷 P1541 乌龟棋 & [NOIP2010提高组](dp)

    传送门 解题思路 一道裸的dp. 用dp[i][j][k][kk]表示用i个1步,j个2步,k个3步,kk个4步所获得的最大价值,然后状态转移方程就要分情况讨论了(详见代码) 然后就是一开始统计一下几 ...

  7. 洛谷 P1525 关押罪犯 & [NOIP2010提高组](贪心,种类并查集)

    传送门 解题思路 很显然,为了让最大值最小,肯定就是从大到小枚举,让他们分在两个监狱中,第一个不符合的就是答案. 怎样判断是否在一个监狱中呢? 很显然,就是用种类并查集. 种类并查集的讲解——团伙(很 ...

  8. NOIP2010提高组 关押罪犯 -SilverN

    (洛谷P1525) 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”( ...

  9. [NOIP2010] 提高组 洛谷P1525 关押罪犯

    刚才做并查集想到了这道以前做的题,干脆一并放上来 题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可 ...

随机推荐

  1. Zookeeper常用命令行及API

    一.Zookeeper常用命令行 1.启动zookeeper客户端(在启动zookeeper集群后启动进行调试) zkCli.sh 2.查看帮助.操作历史 help.history 3.查看当前Zno ...

  2. Java实现检验一串数字的出栈合法性

    题目描述: 解题思路: 判断出栈合法性的关键在于,对于每一个数,在它后面出栈且比它小的数,必是以降序排列的. 比如说3 4 2 1 5这一组数,对于第一个数 3 来说,后面比它小的数有 1.2,而在4 ...

  3. 线段树(lazy)-hdu1689

    题目链接:https://vjudge.net/problem/HDU-1698 题目描述: 现在Pudge想做一些操作.让我们将钩子的连续金属棒从1编号到N.对于每个操作,Pudge可以将连续金属棒 ...

  4. HYSBZ 4034 【树链剖分】+【线段树 】

    <题目链接> 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权值.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...

  5. 003.Heartbeat MySQL双主复制

    一 基础环境 节点 系统版本 MySQL版本 业务IP 心跳IP Master01 CentOS 7.5 MySQL 5.6 192.168.88.100 192.168.77.100 Master0 ...

  6. RMQ问题 [luogu 3865]

    原题地址 ST表模板题,尝试用单点修改线段树. 原本以为线段树会被卡掉,但是还是险过了.实践证明,快速读入很有用. #include<bits/stdc++.h> using namesp ...

  7. Eclipse块选择快捷键

    快捷键:Shift+Alt+A 功能:可删除复制选中区域中的内容 效果图:

  8. Java笔记(十八)同步和协作工具类

    同步和协作工具类 一.读写锁ReentrantReadWriteLock ReadWriteLock接口的定义为: public interface ReadWriteLock { Lock read ...

  9. java 实验 三 (2)(3)

    (2)编写一个Java程序,声明一个数组,各元素如:{12, 23, 456, 222, 768, 93245}计算出所有元素的和以及所有元素的平均值:SumArray.java(3)编写一个Java ...

  10. ReactNative bug:Application XXX has not bean registered.

    故障现象 当react-native init新项目之后运行react-native run -android/ios时手机报错 Application XXX has not bean regist ...