洛谷P1540机器翻译题解

题解补充信息:

  • 算法1的代码不能完全AC,30分(在相关位置补入提醒)

我们先看一下题目:

题目描述

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

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

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

好复杂呀,这让我怎么做?!不急,只要分几步。


算法1:队列

答题第一步:提取信息

根据题目的信息及数据范围(1≤M≤100,1≤N≤1000)可知:本题考查的是模拟(“内存”插入删除)以及队列 (虽然我是用数组)

答题第二步:构建思路

仔细阅读题目描述,先用人脑进行模拟,例如:

n=5,m=2
输入:1 2 3 2 3

step1:读取到1,不在内存中
内存:1

step2:读取到2,不在内存中
内存:1 2

step3:读取到3,不在内存中(内存已满)

模拟到step3时的情况:内存没有剩余空间(AC关键

继续:

step3:读取到3,不在内存中(内存已满)
内存操作:
	1.内存空间不足,释放1
   	2.1被释放后的空位存入3(注意:这个位置应在最后,即最后插入)
内存:2 3
step4:读取到2,在内存中
step5:读取到3,在内存中

程序结束,输出3

答题第三步:组建代码

回顾一下模拟过程,一步步构建代码。

根据模拟过程发现,“内存”的操作方式是先进先出,符合队列标准,所以先定义一个队列:

queue<int> memory;

读取到不存在内存中的数据时,先进行查找(for循环队列)

for(int i=1;i<=memory.size();i++)
{
	if(memory.front()==x)//x是“单词”
    {
    	found=true;//标记已找到
        break;
    }
    memory.push(memory.front());
    memory.pop();//队列循环
}

接下来加上一个判断,确定是否找到(found派上用场啦!)

if(!found)//没有找到
{
	if(memory.size()==m)//内存已满
	{
		memory.pop();//删除
		memory.push(st);
	}
	else
		memory.push(st);
	ans++;
}

最后输出就行啦!

代码:

#include<bits/stdc++.h>
using namespace std;
int m,n;
int st;
int ans=0;
bool found=false;
queue<int> memory;
int main()
{
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>st;//在线处理
		found=false;
		for(int j=1;j<=memory.size();j++)
		{
			if(memory.front()==st)
			{
				found=true;
				break;
			}
            memory.push(memory.front());
            memory.pop();
		}
		if(!found)
		{
			if(memory.size()==m)
			{
				memory.pop();
				memory.push(st);
			}
			else
				memory.push(st);
			ans++;
		}
	}
	cout<<ans;
}

注意,本代码并不能AC,30分,无法判断0是一个单词的数据(#2数据WA,本提醒详见洛谷@juju的题解,附上原文链接


算法2:数组模拟

这没什么好讲的,把算法1改一下就行。

直接贴代码:

#include<bits/stdc++.h>
using namespace std;
int m,n;
int st;
int memory[101];//“内存”
int _size=0;//当前内存内元素数量
int ans=0;
bool found=false;
void move()//删除后移动元素,复杂度为O(n-1)不超时
{
	for(int i=2;i<=m;i++)
		swap(memory[i],memory[i-1]);
}
int main()
{
	cin>>m>>n;
	memset(memory,-1,sizeof(memory));//统一初始化
	for(int i=1;i<=n;i++)
	{
		cin>>st;
		found=false;
		for(int j=1;j<=_size;j++)//查找
		{
			if(memory[j]==st)
			{
				found=true;
				break;
			}
		}
		if(!found)
		{
			if(_size==m)//内存已满
			{
				memory[1]=-1;//删除
				move();//移动
				memory[_size]=st;//添加新元素
			}
			else
				memory[++_size]=st;//添加新元素
			ans++;
		}
	}
	cout<<ans;//输出
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值