題目
Time Limit: 3000ms ,Memory Limit: 10000KB,Accepted: 5030 ,Total Submissions: 9489
Description
輸入正整數n,按從小到大的順序輸出所有形如abcde/fghij=n的表達式,其中a~ j恰好爲數字0 ~ 9的一個排列, 2≤n<=79。
Input
輸入正整數n
Output
輸出形如abcde/fghij=n的表達式,每行一個
Sample Input
62
Sample Output
79546/01283=62
94736/01528=62
思路:
全排列的時間複雜度太高,所以得在中間剪枝。
我們可以由n得到最小的那個abcde,即最小的fghij,按照數學裏的叫法,把它們叫做被除數和除數。
全排列的經典解法就是讓首位分別與後面數字交換,並遞歸求解後面的那些排列。
可以發現,當我們遞歸到某個位置時,再對子問題去執行排列操作已經沒有意義了
在n固定的前提下,除數越大則被除數越大,我們可以找到最小的5位除數,從而得到最小的可能被除數(不一定滿足數字唯一)去做剪枝
若得到的最小可能被除數位數大於5則找不到。否則在查找過程中,若剛好在第五位的時候,就判斷一下後面五位是否有機會排列得到結果
#include<stdio.h>
#include<time.h>
#define N 11
#define LENGTH 5
int GetNumLength(int num);
void TreaverStr(char *str, int l, int r, int preNum, int n, int *numArray, int *len);
int GetNumForStr(char *str, int l, int r);
void SwapChar(char *str, int l, int r);
int IsValid(int bigNum, int smallNum, int n);
int main(void)
{
int n, preNum = 0, len = 0, tempNum = 0;
int numArray[30] = { 0 };
char info[N] = "9876543210";
clock_t start, stop;
scanf("%d", &n);
start = clock();
preNum = 1234 * n;
if (GetNumLength(preNum) > LENGTH)
return -1;
TreaverStr(info, 0, N - 2, preNum, n, numArray, &len);
for (int i = 0; i < len - 1; i++)
{
for (int j = i + 1; j < len; j++)
{
if (numArray[i] > numArray[j])
{
tempNum = numArray[i];
numArray[i] = numArray[j];
numArray[j] = tempNum;
}
}
}
for (int i = 0; i < len; i++)
{
printf("%d/%d=%d\n", numArray[i] * n, numArray[i], n);
}
stop = clock();
printf("用時:%lf\n", (double)(stop - start) / CLK_TCK);
getchar();
getchar();
getchar();
return 0;
}
void TreaverStr(char *str, int l, int r, int preNum, int n, int *numArray, int *len)
{
int flag = 1, pN = 0, lN = 0;
if (l >= r)
{
pN = GetNumForStr(str, 0, LENGTH - 1);
lN = GetNumForStr(str, LENGTH, r);
if (!IsValid(pN, lN, n))
return;
numArray[*len] = lN;
*len = *len + 1;
return;
}
for (int i = l; i <= r; i++)
{
flag = 1;
SwapChar(str, l, i);
if (i == LENGTH - 1 && GetNumForStr(str, 0, i) < preNum)
flag = 0;
if (1 == flag)
TreaverStr(str, l + 1, r, preNum, n, numArray, len);
SwapChar(str, l, i);
}
}
int IsValid(int bigNum, int smallNum, int n)
{
return smallNum * n == bigNum ? 1 : 0;
}
void SwapChar(char *str, int l, int r)
{
char ch = str[l];
str[l] = str[r];
str[r] = ch;
}
int GetNumForStr(char *str, int l, int r)
{
int num = 0;
while (l <= r)
num = num * 10 + str[l++] - '0';
return num;
}
int GetNumLength(int num)
{
int len = 1;
if (num < 0)
return num *= -1;
while ((num /= 10))
{
++len;
}
return len;
}