题目来源:http://download.youkuaiyun.com/detail/zhou20071801/6276543
第一题:
第二题:
第三题:
总结:第一、二题比较水,第三题对3^8=6561种状态如何方便的遍历是个问题,联想到以前做的一道题http://blog.youkuaiyun.com/hntyzhangpeng/article/details/38421859 里用0/1二进制数表示两种状态,使用一个数来遍历所有可能的状态。这里采用了类似的方法,只是换成了3进制数,数用一个数组表示,编写状态变化函数,每次递增1,每个位3个状态,即3进制数:0-空白(连接符),1-加号,2-减号这样可以确保所有的状态都遍历到。
与此算法类似的其他人的一个解如下链接:http://blog.youkuaiyun.com/KeepThinking_/article/details/8521975
以下附上个人的代码,自觉写的还比较简洁:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<list>
#include<stack>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
char flag[8]={0}; //8 slots; 0 --no 1--'+' 2--'-'
//状态变化函数,每次递增1,每个位3个状态,即3进制数:0-空白(连接符),1-加号,2-减号
//遍历满时返回-1,其他情况返回0
//共 3^8(3的8次方)= 6561 种状态
int next(){
int num = 0;
int carry = 0;
//每次递增1,每个位3个状态,即3进制数
flag[0]++;
for(int i=0;i<=7;i++){
if(flag[i]>2){
if(i==7)
return -1; //计算满
flag[i] = 0;
flag[i+1]++;
}
else
break;
}
return 0;
}
//1_2_3_4_5_6_7_8_9 其中'_'处可以有三种状态,0 空白(连接符),1 加号 ,2 减号
int main(){
#ifndef ONLINE_JUDGE
//freopen("testCase.txt","r",stdin);
#endif
int sum =0;
int cnt=0;
int operand = 0;
int expectValue = 0;
char operation = 0;
while(scanf("%d",&expectValue)!=EOF){
//初始化
cnt = 0;
for(int i=0;i<8;i++)
flag[i] = 0;
//遍历所有状态
do{
sum = 0;
operand = 1;
operation = '+';
for(int i=2;i<=10;i++){
if(i==10){
sum += (operation =='+')? operand:-operand;
break;
}
if(flag[i-2]==0) //连接符
operand = 10*operand + i;
else if(flag[i-2]==1||flag[i-2]==2){// + -
sum += (operation =='+')? operand:-operand;
operand = i;
if(flag[i-2]==1)
operation = '+';
else
operation = '-';
}
}
if(sum ==expectValue)
cnt++;
}while(!next());
printf("%d\n",cnt);
}
//fclose(stdin);
return 0;
}