某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪:
(1)每位选手需要回答10个问题(其编号为1到10),越后面越有难度。答对的,当前分数翻倍;答错了则扣掉与题号相同的分数(选手必须回答问题,不回答按错误处理)。
(2)每位选手都有一个起步的分数为10分。 某获胜选手最终得分刚好是100分,如果不让你看比赛过程,你能推断出他(她)哪个题目答对了,哪个题目答错了吗?
(3)如果把答对的记为1,答错的记为0,则10个题目的回答情况可以用仅含有1和0的串来表示。例如:0010110011 就是可能的情况。
(4) 你的任务是算出所有可能情况。每个答案占一行。
方法1:暴力搜索
#include "stdio.h"
void main()
{
long sum=10;
int a1,a2,a3,a4,a5,a6,a7,a8,a9,a10;
for(a1=0;a1<2;a1++){
for(a2=0;a2<2;a2++){
for(a3=0;a3<2;a3++){
for(a4=0;a4<2;a4++){
for(a5=0;a5<2;a5++){
for(a6=0;a6<2;a6++){
for(a7=0;a7<2;a7++){
for(a8=0;a8<2;a8++){
for(a9=0;a9<2;a9++){
for(a10=0;a10<2;a10++){
sum=10;
sum=(a1==0)?(sum-1):(sum*2);
sum=(a2==0)?(sum-2):(sum*2);
sum=(a3==0)?(sum-3):(sum*2);
sum=(a4==0)?(sum-4):(sum*2);
sum=(a5==0)?(sum-5):(sum*2);
sum=(a6==0)?(sum-6):(sum*2);
sum=(a7==0)?(sum-7):(sum*2);
sum=(a8==0)?(sum-8):(sum*2);
sum=(a8==0)?(sum-9):(sum*2);
sum=(a10==0)?(sum-10):(sum*2);
if (sum==100)
printf("%d%d%d%d%d%d%d%d%d%d\n",a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
}
}
}
}
}
}
}
}
}
}
}
方法2:改进的暴力搜索
#include "stdio.h"
void main()
{
for(int number=0;number<1024;number++)
{
int sum=10;
int temp=number;
for(int j=1;j<=10;j++){
sum=(temp%2==1)?(sum*2): (sum-j);
temp=temp/2;
}
if (sum==100)
{
temp=number;
for(int j=0;j<10;j++){
printf("%d",temp%2);
temp=temp/2;
}
printf("\n");
}
}
}
3、递归
#include "stdio.h"
void answer(int a[10],int sum, int index)
{
if (index<=10)
{
sum=(a[index-1]==0)? (sum-index):(sum*2);
a[index]=0; answer(a,sum,index+1);
a[index]=1; answer(a,sum,index+1);
}
if(sum==100 && index==10)
{
for(int i=0;i<10;i++)
printf("%d",a[i]);
printf("\n");
}
}
void main()
{
int a[10], sum=10;
a[0]=0; answer(a,sum,1);
a[0]=1; answer(a,sum,1);
int ch=getchar();
}
4、逆序递归
#include<stdio.h>
void f(char a[], int n, int sum)
{
if (n == 0)
{
if (sum == 10)
puts(a);
return;
}
a[n - 1] = '0'; //每一次调用都会分两条路走,所以就形成了外层一次,内层遍厉一遍,牛x。
f(a, n - 1, sum + n);
if (sum % 2 == 0)
{
a[n - 1] = '1';
f(a, n - 1, sum / 2);
}
}
void main()
{
char a[10];
a[10] = '\0';
f(a, 10, 100);
}