1. 程式人生 > >全排列(洛谷1061 Jam的計數法or NOIP 2006 普及組 第三題)

全排列(洛谷1061 Jam的計數法or NOIP 2006 普及組 第三題)

div 順序 pre highlight 格式 其中 字符 是個 true

Jam是個喜歡標新立異的科學怪人。他不使用阿拉伯數字計數,而是使用小寫英文字母計數,他覺得這樣做,會使世界更加豐富多彩。

在他的計數法中,每個數字的位數都是相同的(使用相同個數的字母),英文字母按原先的順序,排在前面的字母小於排在它後面的字母。我們把這樣的“數字”稱為Jam數字。在Jam數字中,每個字母互不相同,而且從左到右是嚴格遞增的。每次,Jam還指定使用字母的範圍,例如,從2到10,表示只能使用{b,c,d,e,f,g,h,i,j}這些字母。如果再規定位數為5,那麽,緊接在Jam數字“bdfij”之後的數字應該是“bdghi”。(如果我們用U、V依次表示Jam數字“bdfij”與“bdghi”,則U<V,且不存在Jam數字P,使U<P<V)。

你的任務是:對於從文件讀入的一個Jam數字,按順序輸出緊接在後面的5個Jam數字,如果後面沒有那麽多Jam數字,那麽有幾個就輸出幾個。

輸入格式:

輸入有2行,第1行為3個正整數,用一個空格隔開:

s t w (其中s為所使用的最小的字母的序號,t為所使用的最大的字母的序號。w為數字的位數,這3個數滿足:1≤s<T≤26, 2≤w≤t-s )

第2行為具有w個小寫字母的字符串,為一個符合要求的Jam數字。

所給的數據都是正確的,不必驗證。

輸出格式:

輸出最多為5行,為緊接在輸入的Jam數字後面的5個Jam數字,如果後面沒有那麽多Jam數字,那麽有幾個就輸出幾個。每行只輸出一個Jam數字,是由w個小寫字母組成的字符串,不要有多余的空格。

輸入樣例#1:
  2 10 5
  bdfij
輸出樣例#1:
bdghi
bdghj
bdgij
bdhij
befgh
轉自百度文庫:
由於Jam數字有w位,且按照遞增順序排列,因此第w位的最大字母序號為t,第w-1位的最大字母序號為t-1,…,由右而左依次遞減。顯然,第i位的最大字母序號為t+i-w,對應的字符為chr(ord(‘a‘)-1+t+i-w)。設當前的Jam數為ans。由右而左計算未達到最大字母的位置l
Ans[i]=chr(ord(‘a‘)-1+t+i-w)(l+1≤i≤n)
Ans[l]≠chr(ord(‘a’)-1+t+l-w);
則位置l的序數加1(ans[l]=chr(ord(ans[l])+1)),且後綴字符的序數依次遞增1(ans[i]=chr(ord(ans[i-1])+1),l+1≤i≤n)。算法復雜度O(1)。
設初始的Jam數字為st;後繼的Jam數字為ans;緊接在輸入的Jam數字後面的Jam數字個數為tot;調整的起始位置為l
我的代碼:
#include<bits/stdc++.h>
using namespace std;
int Map[200];
char s[2000];
int ss,t,w;

int main()
{
	cin>>ss>>t>>w;
	Map[w-1]=t;
	for(int i=w-2;i>=0;i--)
	  Map[i]=Map[i+1]-1;
	cin>>s;
	int len=strlen(s)-1;
	int temp=5;
	while(temp--)
	{
		for(int i=len;i>=0;i--)
		{
		   if(s[i]!=Map[i]+‘a‘-1)
		   {
		      s[i]+=1;
		      for(int k=i+1;k<=len;k++)
		         s[k]=s[k-1]+1;
		      for(int i=0;i<=len;i++)
		         cout<<s[i];
		        cout<<endl;
		       break;
		   }
		}
	}
    return 0;
}




全排列(洛谷1061 Jam的計數法or NOIP 2006 普及組 第三題)