题目:
根据上排给出十个数,在其下排填出对应的十个数
要求下排每个数都是先前上排那十个数在下排出现的次数。
上排的十个数如下:
【0,1,2,3,4,5,6,7,8,9】
举一个例子,
数值: 0,1,2,3,4,5,6,7,8,9
分配: 6,2,1,0,0,0,1,0,0,0
0在下排出现了6次,1在下排出现了2次,
2在下排出现了1次,3在下排出现了0次....
数学上的理解:
上排数字0 1 2 。。。n-1,则下排数字之和为n,因为下排每个数字都是对应的上排在下排出现的次数,下面一共n个坑,第一个占x个,还剩下n-x个坑,还需要n-x个数需要分配,所以下排数字和为n,则上排中较大的数字基本都是零,只有一个不为零,对应下排中总共0的个数。1+2+3=6了,倘若3下面不为零,则下面至少有3个数字下面不是零,显然不满足。所以只能1 2下面不为零。0 1 2和后面大数有一个不为零,共计4个不为零,则0下面6 那么大数就是6 6下面是1 1和2下面的1*x+2*y=10-6=4 x=2 y=1 退出 6 2 1 0 0 0 1 0 0 0
n = 19
0 1 2 3 4 5 6 7 8 9.。。19
同样方法推出:
16 2 1 。。。。 1 0 0 0
网上的一个回溯试探法:
不断去测试,直到所有的对应位数字符合要求,则success。
#include <iostream.h>
#define len 10
class NumberTB
{
private:
int top[len];
int bottom[len];
bool success;
public:
NumberTB();
int* getBottom();
void setNextBottom();
int getFrequecy(int num);
};
NumberTB::NumberTB()
{
success = false;
//format top
for(int i=0;i<len;i++)
{
top[i] = i;
}
}
int* NumberTB::getBottom()
{
int i = 0;
while(!success)
{
i++;
setNextBottom();
}
return bottom;
}
//set next bottom
void NumberTB::setNextBottom()
{
bool reB = true;
for(int i=0;i<len;i++)
{
int frequecy = getFrequecy(i);
if(bottom[i] != frequecy)
{
bottom[i] = frequecy;
reB = false;
}
}
success = reB;
}
//get frequency in bottom
int NumberTB::getFrequecy(int num) //此处的num即指上排的数 i
{
int count = 0;
for(int i=0;i<len;i++)
{
if(bottom[i] == num)
count++;
}
return count; //cout即对应 frequecy
}
int main()
{
NumberTB nTB;
int* result= nTB.getBottom();
for(int i=0;i<len;i++)
{
cout<<*result++<<endl;
}
return 0;
}