日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数字全排列

發布時間:2023/12/20 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数字全排列 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意;
從1~9之間順序取N個數字,組成每位數不重復的所有可能的N位數,按從小到大的順序進行編號,當輸入其中的任何一個數M是,能找出該數對應的編號。如:當N = 3,M = 132時,則輸出: [123(1), 132(2), 213(3), 231(4), 312(5), 321(6)]——> X = 2

Input
輸入只有一行,兩個正整數N和M(1 ≤ N ≤ 9,1 ≤ K ≤ 987654321),之間用一個空格分隔開。

Output
輸出對應的編號X。
Sample Input
3 132
Sample Output
2

這類題 其實就是讓我們來對數的全排列

首先簡單的說一下思路: 例如 數字 3142 他前面一定有1和2 開頭之后剩下三個數的全排列 也就是階乘;所以一定會用到階乘不妨就寫一個階乘函數,當然這個階乘函數引入的不是這個位的位數 而是 這個位數-1的階乘 。這一點應該很好理解。之后就來研究該怎么處理這個階乘。 3的話,在它之前一定有1,2的全排也就是階乘乘以二。
中間一點錯誤:一開始我是用這個數減一后來考慮到后面就不對了 1先跳過,看4 他要是按這種方法的話就是3種 可是他跟最后一位最多2個數字就2種情況 :42 , 24 ;
正確思路 :找到逆序數也就是比他位數低,而且數值也比這位數小 像 3142 一樣就是2*(3!)*0*(2!)*1*(1)=13;
# include<stdio.h> int solve(int num) {int sign=1,i;for(i=1;i<=num;i++)sign*=i;return sign; } int main() {char str[20];int n,sum=0,count=0,i,j;scanf("%d %s",&n,str);for(i=0;i<n-1;i++){count=0;for(j=i+1;j<n;j++)if(str[j]<str[i])count++;//計算逆序數sum+=count*solve(n-i-1);//后面可能出現的情況計算}printf("%d\n",sum+1);return 0;}

方法二: 深搜

深搜這種方法也不用大說直接看代碼吧。

#include<stdio.h>//深度搜索 # include<string.h> int n,loop,vis[100],j,result[100],Count,sign; char str[100]; void DFS(int step) {int i;sign=0;if(step==n+1)//結束{Count+=1;for(i=1;i<=n;i++){if(result[i]==str[i-1]-'0')//判斷找得這個數是不是需要的那個數sign+=1;}if(sign==n)//是這個數loop=Count;//這就是那個數排序后的序號return;}for(i=1;i<=n;i++)//從一看是dfs{if(!vis[i]){vis[i]=1;//標記這個數用過避免重復使用result[step]=i;DFS(step+1);vis[i]=0;//還原}} } int main() {scanf("%d %s",&n,str);memset(vis,0,sizeof(vis));Count=0;sign=0;DFS(1);//從一開始dfsprintf("%d\n",loop);return 0; }

方法三:

這種方法其實是中用c++中的一種函數next_permutation和prev_permutation 現在還沒大搞懂 ```cpp //第一種方法在algorithm里面有個next_permutation可以實現,排序道理是一樣的 //如果把next_permutation換成prev_permutation,一開始賦值就應是倒序,如:321 # include # include # include using namespace std; int main() { int num,count=0,i; char str[20],s[20]; cin>>num>>str; for(i=0;i
//換位的遞歸思想還不錯,就是沒按字典順序來,僅供看思想 # include<iostream> using namespace std; char str[20]; int t,leap; void Swap(int *a,int *b)//重視 {int temp;temp=*a;*a=*b;*b=temp; } void Array(int *s,int Count,int n) {if(leap)return;if(Count==n){t++;int sign=0;for(int i=0;i<=n;i++)if(s[i]==str[i]-'0')sign++;if(sign==n+1){cout<<t<<endl;leap=1;}return;}for(int i=Count;i<=n;i++){Swap(&s[i],&s[Count]);Array(s,Count+1,n);Swap(&s[i],&s[Count]); }} int main() {int s[20];int num,i;while(cin>>num>>str){t=0;leap=0;for(i=0;i<num;i++)s[i]=i+1;Array(s,0,num-1);}return 0; }

總結

遇到這類題往枚舉,深搜上想好點,畢竟時間復雜度太大
最大8^8 這種好想點 ,再者就是找先規律。當然也不要每個題都能找得到規律,功夫不到家就是白忙活,所以,Fighting!!!

總結

以上是生活随笔為你收集整理的数字全排列的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。