机器翻译(模拟)

题面(from luogu)
(背景: 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。)
这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。
假设内存中有 M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过 M−1 ,软件会将新单词存入一个未使用的内存单元;若内存中已存入 M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。
假设一篇英语文章的长度为 N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

输入格式:
共 2 行。每行中两个数之间用一个空格隔开。
第一行为两个正整数 M,N ,代表内存容量和文章的长度。
第二行为 N 个非负整数,按照文章的顺序,每个数(大小不超过 1000 )代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。
输出格式:
一个整数,为软件需要查词典的次数。
样例.in
3 7
1 2 1 5 4 4 1
样例.out
5
说明:
每个测试点 1s
对于 10% 的数据有 N≤5,M=1 。
对于 100% 的数据有 0≤M≤100,0≤N≤1000 。
整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:
空:内存初始状态为空。
1. 11 :查找单词1并调入内存。
2. 12 :查找单词 2 并调入内存。
3. 12 :在内存中找到单词 1 。
4. 125 :查找单词 5 并调入内存。
5. 254 :查找单词 4 并调入内存替代单词 1 。
6. 254 :在内存中找到单词 4 。
7. 541 :查找单词1并调入内存替代单词 2 。
共计查了 5 次词典。

题目分析
题目概述:给出一串数字,共计n个,你有一个长度最多为m的数字串,如果串中没有当前遇到的数字,需要添加,但如*果该串的长度在加上后大于m,则需要向前挤出位子,即是删去第一个,其他的向前移动一个单位,空出的给新的数字。(题目的样例说明说的很清楚)*
大家有没有发现,这题很像队列,先进,先出,所以我们便可以如此结合题目要求,进行模拟了

在对队列的维护中,我先是写了一个自己都不知道逻辑(瞎扯)的算法即如下:

t=f[d];
f[d]=p;
for(int i = d - 1; i >= 1; i--)
{
    if (i % 2 == 0) //这个就很那什么了。。。额。。。
            { 
                t1=f[i]; //两个变量螺旋交换(无视我在瞎扯)
                f[i]=t;             
            }           
                else
                    {
                        t=f[i];
                        f[i]=t1; 
                    }   

这么去维护的话,自然要错了(AC WA WA WA AC WA AC WA WA WA),所以想出了这样的写法:

for(int i = 1; i <= d-1; i++) 
    f[i]=f[i+1];    //从前向后推
f[d]=p; //霸占挤出的位置

同上面那个额。。。(我也不想多说)好多了。。吧(勉强之笑)

代码

#include <bits/stdc++.h> 
using namespace std;

int k[10009],f[10009],m,n,i,d=1,ans=1; //d的初值要是1,因为是从第一个开始找的,同样,ans也要是1,因为第一个数已经调用了

int find(int c) //判读是否需要维护
{
    for(int i = 1; i <= d; i++)
        if (c == f[i]) return 1; //找到了,直接return
    return 0; //反之,需要进行维护
}

void get_more(int p)
{
    int t=0,t1=0;
    ans++; //进行统计
    if (d < m)  //如果队列没有超出其范围
        {
            d++; //向后拓展一个元素位置
            f[d]=p; //置入
        }
            else 
                {
                //  t=f[d]; //恶心的大宝贝
                //  f[d]=p;
                //  for(int i = d - 1; i >= 1; i--)
                //      {
                //          if (i % 2 == 0)
                //              {
                //                  t1=f[i];
                //                  f[i]=t;             
                //              }           
                //                  else
                //                      {
                //                          t=f[i];
                //                          f[i]=t1; 
                //                      }   

                    for(int i = 1; i <= d-1; i++)
                        f[i]=f[i+1];    //从前向后推
                    f[d]=p;  //霸占挤出的位置
                }
}

int main()
{
    cin>>m>>n;   //输入
    for (int i = 1; i <= n; i++)
        cin>>k[i];

    f[1]=k[1]; //先取第一个
    for (int i = 2; i <= n; i++) //开始处理队列
    {   
        if (find(k[i]) == 0) get_more(k[i]); //判断是否需找
    //  if (d < m) d++; //之前的赘笔,之后再“get_more”函数中已经覆盖此功能了
    //  for (int i = 1; i <= d; i++)
        //cout<<f[i]<<' ';
    //  cout<<endl;
    }

//  for (int i = 1; i <= m; i++)
    //  cout<<f[i];
    cout<<ans; //输出
}
                                               **蒟蒻新星c_uizrp_dzjopkl原创**

猜你喜欢

转载自blog.csdn.net/c_uizrp_dzjopkl/article/details/81635053