大数

// 先将十个数字的21次方手动计算出来,存入初始数组中
// 枚举各个数字所有可能情况
		//可能的情况:每个数字个数之和为不超过21且加和正好为21 
// 对于每一种情况计算加和
// 判断:
		// 所得加和是否为21位数
		// 各个数字个数是否对应相等
// 对最终的答案数组按从小到大排序,然后顺序输出 

/*
 * 总结:
 *	1.调试技巧:分块测试,逐块测试,黑盒测试(只能保证大部分对,不能保证个别细节对,适用于没有什么特殊点的程序的测试) 
 *	2.写程序首先要思路清晰,如本次就写出来描述了,但还有点心急,细节没有仔细考虑周全就写,这样会导致调试时间的耗费,得不偿失,要知道我写程序写了1小时,调试却花了4个小时 
 *	3.写程序能常规尽量常规,因为非常规更容易导致错误;写代码要表现出逻辑性,即使某些步骤可以省略,也要加上以体现其逻辑 
 */ 

#include <iostream>
#include <algorithm>
#include <conio.h>
using namespace std;
#define ANSWER_COUNT 100

int num[10][30] = {
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    {7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 9, 7, 1, 5, 2},
    {11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 6, 0, 3, 5, 3, 2, 0, 3},
    {13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 9, 8, 0, 4, 6, 5, 1, 1, 1, 0, 4},
    {15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 7, 6, 8, 3, 7, 1, 5, 8, 2, 0, 3, 1, 2, 5},
    {17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 9, 3, 6, 9, 5, 0, 6, 4, 0, 3, 7, 7, 8, 5, 6},
    {18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 8, 5, 4, 5, 8, 6, 4, 0, 8, 3, 2, 8, 4, 0, 0, 7},
    {19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8},	// 0.不仔细:抄错 
    {21, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 9, 4, 1, 8, 9, 8, 9, 1, 3, 1, 5, 1, 2, 3, 5, 9, 2, 0, 9}	
};

int ans[100][30];
int p[100];
int _count;

void mul(int _num[], int cnt, int res[]) 
{
     int i;
     int tmp = 0;
     for (i = 29; i >= 29 - _num[0] + 1; i--) {
         tmp += cnt * _num[i];	// 4.此处的称号竟然写成了+,同下为 "心手不一的潜意识思维定势"
         res[i] = tmp % 10;
         tmp /= 10; 
     }
     while (tmp > 0) {
         res[i--] = tmp % 10;
         tmp /= 10; 
     }
     
     if (cnt == 0)		// 6.[bug]注意!!! :只有0会缩减数位,所以0还是具有其特殊性,此处不能一概写成res[0] = 29 - i; 
     	res[0] = 1;
     else
     	res[0] = 29 - i;
}

void add(int num1[], int num2[]) 
{
     int i;
     int tmp = 0;
     int n = max(num1[0], num2[0]);
     for (i = 29; i >= 29 - n + 1; i--) {
         tmp += num1[i] + num2[i];
         num1[i] = tmp % 10;
         tmp /= 10;
     }   
     while (tmp > 0) {
         num1[i] = tmp % 10;
         tmp /= 10;
     }   
     num1[0] = 29 - i;
}

bool test(int res[], int arr[]) {
	int cnt[10] = { 0 };
	for (int i = 29; i >= 29 - res[0] + 1; i--) {
		cnt[res[i]]++;
	}
	for (int i = 0; i < 10; i++) {
		if (cnt[i] != arr[i]) return false;
	}
	return true;
}

void dfs(int arr[], int cur) 
{
     if (cur >= 9) {	// 1.此步忘掉了一个关键的条件:数组所有的和必须为21才行 
     	int sum = 21; 
     	for (int i = 0; i < 9; i++) {	// 3.此处竟然写成了i < 10, 应是减去9前面的,心理是这么想的,但写出又是另外一回事思维定势热惹得祸 
     		sum -= arr[i];
     	}
		arr[9] = sum;
     	
        int res[30] = {0};
        res[0] = 1;	// 5.为了避免意想不到的漏洞,这句还是要加上 
        int tmp[30] = {0};
        for (int i = 0; i < 10; i++) {
            mul(num[i], arr[i], tmp);
            add(res, tmp);
        }
        if (res[0] == 21 && test(res, arr) == true) {	 
           for (int i = 0; i < 30; i++) {
               ans[_count][i] = res[i];
           } 
           _count++;	// 2.低级错误,将此部分写到上面的循环里了 
    	}
        return;
     }
     
     int tmp = 21;
     for (int i = 0; i < cur; i++) tmp -= arr[i];
	 int arr_cur = arr[cur];
     for (int i = 0; i <= tmp; i++) {
         arr[cur] = i;
         dfs(arr, cur + 1);
     }
     arr[cur] = arr_cur;
}


int cmp(int num1[], int num2[])
{
     if (num1[0] != num2[0]) 
        return num1[0] > num2[0] ? 1 : 0;
     int n = num1[0];
     for (int j = 29 - n + 1; j <= 29; j++) {
         if (num1[j] != num2[j])
            return num1[0] > num2[0] ? 1 : 0;
     }
} 

void my_sort() 
{
     int k = 0;
     int tmp;
     int flag[ANSWER_COUNT] = { 0 };
     for (int i = 0; i < _count; i++) {
     	if (!flag[i]) {
     		tmp = i;
	     	for (int j = 0; j < _count; j++) {
	     		if (j !=i && !flag[j] && cmp(ans[j], ans[i]) == 1) {
	     			tmp = j;
	     		}
	     	}
	     	p[k++] = tmp;
	     	flag[tmp] = 1;
	     }
     } 
}

int main()
{
    int arr[10];
    
    _count = 0;
    dfs(arr, 0);
    my_sort();
    
    
    for (int i = 0; i < _count; i++) {
    	int j = p[i];
        for (int k = 29 - ans[j][0] + 1; k <= 29; k++) {
            cout << ans[j][k];
        }
        cout << endl;
    }
    
    return 0;
}

  

posted on 2014-03-21 23:57  Gddxz  阅读(217)  评论(0编辑  收藏  举报

导航