題目描述:火星人共有n個手指,每個手指分別代表著1-n共n個數,可以通過改變這個這n個手指的順序來改變值的大小。但是人類想要和火星人交流,就必須通過科學家,科學家先將火星人講的話(手指表示的數)翻譯成我們能理解的語言(如火星人共3個手指,則123 132 213 231 312 321分別代表1 2 3 4 5 6),然後告訴你乙個數,你把這個數和火星人講的話加起來回給科學家,科學家再翻譯成火星人的語言。本題給出火星人的手指數n、要加的數m和手指的順序num[n],要求輸出火星人收到的回話。
剛開始看到這個題目,還是有點懵逼的,但是知道它是乙個全排列問題,所以趕緊的去了解了一下全排列,順利地解決了這個問題。
本題就是要求求出num[n]經過m次排列後的結果。
對於一系列的數,比如int num[5] = 這個陣列,要想對它進行全排列,要經過以下幾個步驟:
1.判斷該陣列能不能進行全排列
對於乙個陣列來說,如果他為num[5] = ,那麼也就沒有必要再去全排列了,因為他已經是最大的數字了,沒有後繼。所以,想要判斷一系列數能不能進行全排列,判斷他有沒有後繼(即這個數是否存在非遞減的兩個數),如果有(存在),那就可以進行排列。
判斷是否能進行全排列的**:
bool hasnext()
2.如何進行全排列(當時想這個想了挺久的==)
在確定這一系列的數有後繼之後,那如何去找到它的後繼呢?要明確,乙個數的後繼要滿足兩個條件:比這個數大、在比這個數大的數裡面最小。
首先,我們從右往左遍歷這個陣列,找出乙個數num[i],滿足num[i]>num[i-1],然後用top將這個i記錄下來(即top為極大值點),並且確定了乙個要交換的數num[top-1];
接著,我們要確定第二個要交換的數, 而第二個要交換的數為num[top]-num[n]中最小的數並且這個數要大於第乙個被交換的數num[top-1];
然後,交換兩個數;
最後,如果交換之後,num[top]及其後面的數如果還是單調遞減的,那就將其位置對調,得到最小的。
找出極大值得top並記錄
for( int i = n-1; i >0; i--)
}
確定第二個要交換的數
int mm = top;//mm為要交換數的下標
//如果top後面還有比top前面的數(也就是num[top-1)小的話,就先交換那個小的數
for( int i = top; i < n; i++)
交換兩個數
void _swap( int *a, int *b)
_swap(&num[mm],&num[top-1]);
得到最小
for(int i=0;i<=(top+n-1)/2-top;i++)
_swap(&num[i+top],&num[n-1-i]);
大概的思路就是這個樣子了==
可能講的還不是太清楚,其實對於全排列問題,用遞迴、c++的庫函式都可以完成的。
原始碼:
#includeusing namespace std;
const int maxn = 10000+5;
int num[maxn];
int n,m;
//個人覺得這個不寫也沒問題,但是為了安全,還是寫著吧
int hasnext()
void _swap( int *a, int *b)
void next()
//找出第二個要交換的數
int mm = top;
for( int i = top; i < n; i++)
_swap( &num[top-1], &num[mm]);
for( int i = 0; i <= (top+n-1)/2-top; i++)
_swap( &num[i+top], &num[n-1-i]);
}int main()
printf("%d",num[0]);
for( int i = 1; i < n; i++)
printf(" %d",num[i]);
printf("\n");
}return 0;
}
//用vector容器不用陣列更容易實現呢==
用c++中的庫函式
#include#includeusing namespace std;
const int maxn = 10000+5;
int num[maxn];
int main()
return 0;
}
NOIP普及組 火星人 貪心,排列)
人類終於登上了火星的土地並且見到了神秘的火星人。人類和火星人都無法理解對方的語言,但是我們的科學家發明了一種用數字交流的方法。這種交流方法是這樣的,首先,火星人把乙個非常大的數字告訴人類科學家,科學家破解這個數字的含義後,再把乙個很小的數字加到這個大數上面,把結果告訴火星人,作為人類的回答。火星人用...
NOIP2004P4 火星人 題解
題目描述略 本題題意為求給定長度為 n 的數列的後第 m 個全排列 字典序 從右向左查詢最大的下標 i 0 i n 1 使得 a i a i 1 從左向右查詢最小的元素 a j i 1 j n 1 使得 a i a j 交換 a i 和 a j 逆置翻轉 a i 1 n 1 演算法分析 我們可以發現...
P1088 NOIP2004 普及組 火星人
目錄演算法求解 參考文章 題目傳送門 題目描述 人類終於登上了火星的土地並且見到了神秘的火星人。人類和火星人都無法理解對方的語言,但是我們的科學家發明了一種用數字交流的方法。這種交流方法是這樣的,首先,火星人把乙個非常大的數字告訴人類科學家,科學家破解這個數字的含義後,再把乙個很小的數字加到這個大數...