集合的前N個元素

【問題描述】
  編一個程序,按遞增次序生成集合M的最小的N個數(n個數各不相同,n<100),M的定義如下:
    (1)數1屬於M;
    (2)如果X屬於M,則Y=2*x+1和Z=3*x+1也屬於M;
 (3)此外再沒有別的數屬於M。
【輸入格式】
只有一行,爲一整數n(0<n<100)。
【輸出格式】
只有一行,爲遞增的n個數。
【樣例輸入】
10
【樣例輸出】
1 3 47 9 10 13 15 19 21

問題分析

可以用兩個隊列a和b來存放新產生的數,然後通過比較大小決定是否輸出,具體方法如下:

     (1)初始時a,b隊列隊首值爲1                              

     (2)計算2*x+1和3*x+1分別放入隊列a和隊列b的隊尾

     (3)將隊列a和隊列b的頭結點進行比較,可能有三種情況:

         (A)a.front()<b.front()  輸出a.front(),a隊首並出隊

         (B)a.front()=b.front()輸出a.front(),a,b隊首均出隊

         (C)a.front()>b.front()輸出b.front(),b隊首並出隊

     (4)重複(2),(3)直至取出第N項爲止。

注意x應該爲當前出隊的數的值

c++代碼

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k;
int a[20],b[20];
bool f[10000];//數組千萬不要開小了,因爲數會變,4位數至少開1萬 
queue<int> q;
void init();
void work();
int main()
{
	//freopen("produce5.in","r",stdin);
	init();
	work();	
	return 0;
}
void init()
{
	memset(f,0,sizeof(f));
	cin>>n;
	cin>>k;
	for(int i=1;i<=k;i++) cin>>a[i]>>b[i];	
}
void work()
{
	int tot=0;
	f[n]=true;//標記n已出現 
	q.push(n);//把n進隊 
	tot++;	
	while(!q.empty())//隊列非空 
	{
		int x=q.front();//對隊首的每一位進行操作		
		int wei=1;//記錄當前處理的是那一位,第一位時爲1,第二位時時10……100				
		while(x>0)
		{
			int temp=x%10;//取個位			
			for(int i=1;i<=k;i++)
			{
				if(temp==a[i])
				{
					int p=q.front()+(b[i]-temp)*wei;//好好理解					
					if(!f[p])//如果p沒出現過,進隊,並設爲已出現 
					{						
						q.push(p);
						f[p]=true;
						tot++;						
					}
				}
			}
			x=x/10;			
			wei*=10;
		}
		q.pop();
	}
	cout<<tot<<endl;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章