NOIP2010提升組 機器翻譯

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

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

總時間限制: 1000ms 內存限制: 65536kB
描述

小晨的電腦上安裝了一個機器翻譯軟件,他常常用這個軟件來翻譯英語文章。ide

這個翻譯軟件的原理很簡單,它只是從頭至尾,依次將每一個英文單詞用對應的中文含義來替換。對於每一個英文單詞,軟件會先在內存中查找這個單詞的中文含義,若是內存中有,軟件就會用它進行翻譯;若是內存中沒有,軟件就會在外存中的詞典內查找,查出單詞的中文含義而後翻譯,並將這個單詞和譯義放入內存,以備後續的查找和翻譯。spa

假設內存中有M個單元,每單元能存放一個單詞和譯義。每當軟件將一個新單詞存入內存前,若是當前內存中已存入的單詞數不超過M−1,軟件會將新單詞存入一個未使用的內存單元;若內存中已存入M 個單詞,軟件會清空最先進入內存的那個單詞,騰出單元來,存放新單詞。翻譯

假設一篇英語文章的長度爲N個單詞。給定這篇待譯文章,翻譯軟件須要去外存查找多少次詞典?假設在翻譯開始前,內存中沒有任何單詞。code

輸入
輸入文件共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 次詞典。

算法分析:blog

用隊列先進先出的特性模擬內存存放單詞;用一個一維數組標記某一個單詞是否在於內存中以便快速肯定是否須要查找詞典。其他的基本就是純粹模擬了。隊列

有一點須要注意:如果使用循環隊列,須要好好檢查循環隊列中元素個數的計算是否正確。內存

代碼一:不使用循環隊列,直接把隊列定義得足夠大io

 1 #include<stdio.h>
 2 #define maxQueueLength 1005
 3 int main()
 4 {
 5     int M,N;
 6     int que[maxQueueLength]={0},check[1005]={0}; // que[]是循環隊列,用來模擬內存;check[i]==1表示i在內存中。
 7     int ans=0,begin,end,i,t;
 8     scanf("%d%d",&M,&N);
 9 
10     begin=end=0;//初始化隊列
11     for(i=0;i<N;i++)
12     {
13         scanf("%d",&t);
14         if(check[t]==0)//查找內存,發現內存中沒有t存在
15         {
16             ans++;//查找字典的次數增長一次
17             //如今開始作單詞放進內存的過程
18             if(end-begin<M)
19             {
20                 que[end++]=t;
21             }
22             else //end-begin>=M
23             {
24                 check[que[begin]]=0;
25                 begin++;
26                 que[end++]=t;
27             }
28             check[t]=1;//標記t已經在內存中
29         }
30     }
31     printf("%d\n",ans);
32     return 0;
33 }
View Code

代碼二:使用循環隊列,節省一些隊列空間

 1 #include<stdio.h>
 2 #define maxQueueLength 105
 3 int main()
 4 {
 5     int M,N;
 6     int que[maxQueueLength]={0},check[1005]={0}; // que[]是循環隊列,用來模擬內存;check[i]==1表示i在內存中。
 7     int ans=0,begin,end,i,t,count;
 8 
 9     scanf("%d%d",&M,&N);
10 
11     begin=end=0;//初始化隊列
12     for(i=0;i<N;i++)
13     {
14         scanf("%d",&t);
15         if(check[t]==0)//查找內存,發現內存中沒有t存在
16         {
17             ans++;//查找字典的次數增長一次
18             //如今開始作單詞放進內存的過程
19             if(end>=begin) count=end-begin;
20             else count=maxQueueLength-begin+end;
21 
22             if(count<M)
23             {
24                 que[end++]=t;
25                 if(end>=maxQueueLength) end=end%maxQueueLength;
26             }
27             else //end-begin>=M
28             {
29                 check[que[begin]]=0;
30                 begin++;
31                 que[end++]=t;
32                 if(begin>=maxQueueLength)begin=begin%maxQueueLength;
33                 if(end>=maxQueueLength)end=end%maxQueueLength;
34             }
35             check[t]=1;//標記t已經在內存中
36         }
37     }
38     printf("%d\n",ans);
39     return 0;
40 }
View Code

下面的代碼也是用了循環隊列,不過代碼的可讀性可能好一些哈哈哈

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main()
 5 {
 6     int m,n;
 7     int i;
 8     int a[102]={0},count=0;//a[]表示內存的空間。count記錄當前內存中已經存有的單詞個數
 9     int firstIn=0,lastIn=0;//firstIn表示最先進入內存的單詞在內存中的下標。lastIn表示下一個能夠用於存儲新單詞的空閒空間的下標。
10     int b[1005]={0};//b[i]==1表示i這個單詞在內存中。不然表示i不在內存中。
11     int ans=0,t;
12 
13     scanf("%d%d",&m,&n);
14     for(i=0;i<n;i++)
15     {
16         scanf("%d",&t);//依次輸入n個單詞
17         if(b[t]==0)//若單詞t不在內存中
18         {
19             ans++;//須要查一次字典
20 
21             //查完字典後須要把剛查的單詞存入內存
22             if(count<m)//內存空間還有空閒
23             {
24                 a[lastIn]=t;
25                 b[t]=1;
26                 count++;
27                 lastIn++;
28                 lastIn=lastIn%m;
29             }
30             else//內存空間已經滿了
31             {
32                 //先騰空一個位置
33                 b[a[firstIn]]=0;
34                 //a[firstIn]=0;
35                 firstIn++;
36                 firstIn=firstIn%m;
37 
38                 //而後再把新單詞放入內存
39                 a[lastIn]=t;
40                 b[t]=1;
41                 lastIn++;
42                 lastIn=lastIn%m;
43             }
44         }
45     }
46     printf("%d\n",ans);
47     return 0;
48 }
View Code
相關文章
相關標籤/搜索