主题:[讨论]第33次编程比赛第1题题目
goal00001111 [专家分:4030] 发布于 2006-06-29 19:36:00
出个还算简单的,欢迎广大编程爱好者参加!
结果为0的序列:
考虑由1到n(n<=9)按递增顺序排成的序列1234...n,在他们之间加入加号,减号或者什么也不加,分别使它们做加法,减法或者将数字合并.然后求出结果,看看是否为0.
写一个程序,找出所有长度为n的结果为0的序列,返回序列的个数.
函数接口: int ResultIsZero(int n);
其中n表示序列的长度, int表示返回的序列的个数.
举例:
n = 8, 返回10.
序列分别为:1+2+3+4-5-6-7+8 = 0;
1+2+3-4+5-6+7-8 = 0;
1+2-3+4+5+6-7-8 = 0;
1+2-3-4-5-6+7+8 = 0;
1-2+3-4-5+6-7+8 = 0;
1-2-3+4+5-6-7+8 = 0;
1-2-3+4-5+6+7-8 = 0;
1+23-45+6+7+8 = 0;
12-34-56+78 = 0;
1-23-4+5+6+7+8 = 0;
有疑问请到讨论帖讨论!
http://www.programfan.com/club/showbbs.asp?id=178473
回复列表 (共8个回复)
板凳
yxs0001 [专家分:9560] 发布于 2006-06-30 16:48:00
/*出个还算简单的,欢迎广大编程爱好者参加!
结果为0的序列:
考虑由1到n(n<=9)按递增顺序排成的序列1234...n,在他们之间加入加号,减号或者什么也不加,分别使它们做加法,减法或者将数字合并.
然后求出结果,看看是否为0.
写一个程序,找出所有长度为n的结果为0的序列,返回序列的个数.
函数接口: int ResultIsZero(int n);
其中n表示序列的长度, int表示返回的序列的个数.
举例:
n = 8, 返回10.
序列分别为:1+2+3+4-5-6-7+8 = 0;
1+2+3-4+5-6+7-8 = 0;
1+2-3+4+5+6-7-8 = 0;
1+2-3-4-5-6+7+8 = 0;
1-2+3-4-5+6-7+8 = 0;
1-2-3+4+5-6-7+8 = 0;
1-2-3+4-5+6+7-8 = 0;
1+23-45+6+7+8 = 0;
12-34-56+78 = 0;
1-23-4+5+6+7+8 = 0;
*/
#include <iostream>
using namespace std;
void showcode(int code,int n)
{
int i;
cout<<" ";
for(i=0;i<9;i++)
cout<<i+1<<" ";
cout<<"\n ";
for(i=0;i<n;i++){
cout<<(code & 0x1)<<" ";
code >>= 1;
}
cout<<endl;
}
class CCode{
private:
int code;
int n;
int num[9];//转化为数字
int max;
int sum;
int count;
public:
CCode(){};
CCode(int code,int n);
int number(int start,int end);
int cacl();
int check(const int potcode);
void show();
};
CCode::CCode(int ncode,int nn)
{
code = ncode;
n = nn;
max = 0;
sum = 0;
count = 0;
int end = 0,start = 1;
while(ncode){
end++;
if(ncode & 0x1){
num[count] = number(start,end);
sum += num[count];
max = (num[count] > max) ? num[count] : max;
count++;
start = end + 1;
}
ncode >>= 1;
}
}
int CCode::number(int start,int end)
{
int i;
int result = 0;
for(i = start;i<=end;i++){
result *= 10;
result += i;
}
return result;
}
int CCode::check(const int npotcode)
{
int potcode = npotcode;
int positive = num[0];//正数和
int negative = 0;//负数和
int i = 0;
// int t[9] = {0};
// cout<<"运算符code:\n";
// showcode(potcode,count-1);
for(i=1;i<count;i++){
// t[i] = potcode & 0x1;
if(potcode & 0x1)
positive += num[i];
else
negative += num[i];
potcode >>= 1;
}
//显示算式
/*
if(positive == negative){
cout<<"算式:"<<num[0];
for(i=1;i<count;i++){
if(t[i])
cout<<" + ";
else
cout<<" - ";
cout<<num[i];
}
cout<<" = "<<positive - negative<<endl;
}
*/
return positive - negative;
}
int CCode::cacl()
{
if(sum < max + max || count<3)
return 0;
int result = 0;
int potcode = 1 << (count - 1);
while(potcode--){
if(check(potcode) == 0)
result ++;
}
return result;
}
void CCode::show()
{
int i;
cout<<"\n显示数据:\n ";
cout<<"code为:"<<code<<endl;
showcode(code,n);
cout<<" 数字为:\n ";
for(i=0;i<count;i++){
cout<<num[i]<<" ";
}
cout<<endl;
cout<<"共有 "<<count<<" 个数字,其中最大值为:"<<max<<" ,和为:"<<sum<<endl;
}
int ResultIsZero(int n)
{
if(n>9 || n<=2)
return 0;
//要使结果 == 0,须将序列分为3 - n 部分
int code = 1 << n; //01序列
int end = 1 << (n-1);
int result = 0; //满足条件的序列个数
while(--code > end){
if(code == 10)
cout<<"";
CCode ccode(code,n);
// ccode.show();
result += ccode.cacl();
}
return result;
}
int main (void)
{
cout<<"\n";
int i;
for(i=0;i<10;i++){
cout<<"\n i = "<<i<<endl;
cout<<"共有:"<<ResultIsZero(i)<<"个"<<endl;
}
return 0;
}
3 楼
火海时代 [专家分:230] 发布于 2006-06-30 19:49:00
#include <iostream>
using namespace std;
bool daji(int a[],int x,bool bl[])
{
int temp = a[0];
for(int i = 0; i < x; i++)
{
if(bl[i])
temp += a[i+1];
else
temp -= a[i+1];
}
if(!temp)
return true;
return false;
}
int fu(bool bl[],int i,int a[],int x)
{
if(i == x)
return daji(a,x,bl);
int m = 0;
bl[i] = true;
m += fu(bl,i+1,a,x);
bl[i] = false;
m += fu(bl,i+1,a,x);
return m;
}
int suan(int a[],int x)
{
if(x == 1)
return 0;
bool *bl = new bool[x-1];
return fu(bl,0,a,x-1);
}
int m10(int n)
{
if(n == 0)
return 1;
int temp = 10;
for(int i = 1; i < n; i++)
temp *= 10;
return temp;
}
int shuz(int a[],int i,int n,int x)
{
if(i > n)
return suan(a,x);
int temp;
int w = 0;
for(int j = 1; j <= (n-i+1); j++)
{
temp = 0;
for(int k = j; k > 0; k--)
temp += (i+j-k)*m10(k-1);
a[x] = temp;
w += shuz(a,i+j,n,x+1);
}
return w;
}
int ResultIsZero(int n)
{
if(n < 3)
return 0;
int a[9];
return shuz(a,1,n,0);
}
4 楼
eastcowboy [专家分:25370] 发布于 2006-07-01 02:21:00
/*
程序介绍
采用深度优先搜索。
当n==N时返回。
时间复杂度:O(3^N)
三个参数的意义:
n: 表示目前分析到第n个数字,n=0表示第一个。
开始递归时n=1,即是说从数字2开始。(因为数字1始终都放在最前,不加符号)
total:表示目前为止得到的计算结果。但不包括last中的值,因为last还可能变化。
last: 表示从上一个数字开始到最后一次出现+-符号,已经形成的数。
例如,分析到123+45-678时,last=678
current变量:记录当前正在处理的数字的值,正好是n+1。
*/
//===================================================================
// 程序代码
static int N;
static int ResultIsZero_DFS(int n, int total, int last)
{
const int current = n+1;
if( n == N )
return (total+last == 0);
else
return
ResultIsZero_DFS(n+1, total, last*10+current)
+ ResultIsZero_DFS(n+1, total+last, current)
+ ResultIsZero_DFS(n+1, total-last, current);
}
int ResultIsZero(int n)
{
N = n;
return ResultIsZero_DFS(1, 0, 1);
}
//===================================================================
// 以下代码为测试用
#include <iostream>
using std::cout;
using std::endl;
int main(void)
{
int i;
// 正确性测试
for(i=1; i<=9; ++i)
cout << i << '\t' << ResultIsZero(i) << endl;
// 效率测试
cout << "效率测试开始" << endl;
for(i=0; i<3000; ++i)
ResultIsZero(9);
cout << "效率测试结束" << endl;
return 0;
}
5 楼
yxs0001 [专家分:9560] 发布于 2006-07-01 08:28:00
/*出个还算简单的,欢迎广大编程爱好者参加!
结果为0的序列:
考虑由1到n(n<=9)按递增顺序排成的序列1234...n,在他们之间加入加号,减号或者什么也不加,分别使它们做加法,减法或者将数字合并.然后求出结果,看看是否为0.
写一个程序,找出所有长度为n的结果为0的序列,返回序列的个数.
函数接口: int ResultIsZero(int n);
其中n表示序列的长度, int表示返回的序列的个数.
举例:
n = 8, 返回10.
序列分别为:1+2+3+4-5-6-7+8 = 0;
1+2+3-4+5-6+7-8 = 0;
1+2-3+4+5+6-7-8 = 0;
1+2-3-4-5-6+7+8 = 0;
1-2+3-4-5+6-7+8 = 0;
1-2-3+4+5-6-7+8 = 0;
1-2-3+4-5+6+7-8 = 0;
1+23-45+6+7+8 = 0;
12-34-56+78 = 0;
1-23-4+5+6+7+8 = 0;
*/
#include <iostream>
using namespace std;
void showcode(int code,int n)
{
int i;
cout<<" ";
for(i=0;i<9;i++)
cout<<i+1<<" ";
cout<<"\n ";
for(i=0;i<n;i++){
cout<<(code & 0x1)<<" ";
code >>= 1;
}
cout<<endl;
}
class CCode{
private:
int code;
int n;
int num[9];//转化为数字
int max;
int sum;
int count;
public:
CCode(){};
CCode(int code,int n);
int number(int start,int end);
int cacl();
bool check(const int potcode);
void show();
};
CCode::CCode(int ncode,int nn)
{
code = ncode;
n = nn;
max = 0;
sum = 0;
count = 0;
int end = 0,start = 1;
while(ncode){
end++;
if(ncode & 0x1){
num[count] = number(start,end);
sum += num[count];
max = (num[count] > max) ? num[count] : max;
count++;
start = end + 1;
}
ncode >>= 1;
}
}
int CCode::number(int start,int end)
{
int i;
int result = 0;
for(i = start;i<=end;i++){
result *= 10;
result += i;
}
return result;
}
bool CCode::check(const int npotcode)
{
int potcode = npotcode;
int positive = num[0];//正数和
// int negative = 0;//负数和
int i = 0;
// int t[9] = {0};
// cout<<"运算符code:\n";
// showcode(potcode,count-1);
for(i=1;i<count;i++){
// t[i] = potcode & 0x1;
if(potcode & 0x1)
positive += num[i];
// else
// negative += num[i];
potcode >>= 1;
}
//显示算式
/*
if((positive<<1) == sum){
cout<<"算式:"<<num[0];
for(i=1;i<count;i++){
if(t[i])
cout<<" + ";
else
cout<<" - ";
cout<<num[i];
}
cout<<" = "<<(positive<<1) - sum<<endl;
}
*/
// return positive - negative;
return (positive<<1) == sum;
}
int CCode::cacl()
{
//总和为奇数
if(sum & 1)
return 0;
if((sum>>1) < max || count<3)
return 0;
int result = 0;
int potcode = 1 << (count - 1);
while(potcode--){
if(check(potcode))
result ++;
}
return result;
}
void CCode::show()
{
int i;
cout<<"\n显示数据:\n ";
cout<<"code为:"<<code<<endl;
showcode(code,n);
cout<<" 数字为:\n ";
for(i=0;i<count;i++){
cout<<num[i]<<" ";
}
cout<<endl;
cout<<"共有 "<<count<<" 个数字,其中最大值为:"<<max<<" ,和为:"<<sum<<endl;
}
int ResultIsZero(int n)
{
if(n>9 || n<=2)
return 0;
//要使结果 == 0,须将序列分为3 - n 部分
int code = 1 << (n-1); //01序列
int end = 1 << n;
int result = 0; //满足条件的序列个数
while(++code < end){
// if(code == 10)
// cout<<"";
CCode ccode(code,n);
// ccode.show();
result += ccode.cacl();
}
return result;
}
int main (void)
{
cout<<"\n";
int i;
for(i=0;i<10;i++){
cout<<"\n i = "<<i<<endl;
cout<<"共有:"<<ResultIsZero(i)<<"个"<<endl;
}
return 0;
}
6 楼
liangbch [专家分:1270] 发布于 2006-07-01 12:21:00
请问,如何隐藏内容
7 楼
liangbch [专家分:1270] 发布于 2006-07-01 12:31:00
下面是我刚刚完成的一个程序,在VC++6.0调试通过
// 33thmatch2.cpp : Defines the entry point for the console application.
//
//#include "stdafx.h"
#include "stdlib.h"
#include "stdio.h"
#define MAX_LEN 9
struct st_str
{
char *p; //字符串的开始地址
int len; //字符串的长度
};
/*
g:全局变量,表示数字串的一种切分
若len=3,lenArray[0]=3,lenArray[1]=1,lenArray[2]=4
则表示数字串被切分为3段,其它每段长度为3,1,4,
各段数字串为"123","4","5678"
*/
struct
{
int len; //'12345678"被分为len段
char lenArray[MAX_LEN]; //表示各段长度的数组
struct st_str strTable[MAX_LEN]; //表示各段数字串的数组
char signArray[MAX_LEN]; //符号数组,signArray[i]为'+'或者'-'
}g;
char digArray[MAX_LEN]=
{
'1','2','3','4','5','6','7','8','9'
};
//将长为len,地址为p的字符串转化为数
int str2num(char *p,int len)
{
int i,n;
for (n=0,i=0;i<len;i++)
{
n*=10;
n+= (p[i]-'0');
}
return n;
}
void printfExpression(int result)
{
int i,j;
for (j=0;j<g.strTable[0].len;j++)
printf("%c",g.strTable[0].p[j]);
for (i=0;i<g.len-1;i++)
{
printf("%c",g.signArray[i]);
for (j=0;j<g.strTable[i+1].len;j++)
printf("%c",g.strTable[i+1].p[j]);
}
printf("=%d\n",result);
}
//检查某一种数字串切分是含有运算结果为0的表达式,返回表达式的个数
int check()
{
int i,n,count,r,r2,mask;
int zeroExpCount; //结果等于0的表达式的个数
// 共有g.len-1 个'+','-',其排列方式有count种
count= (1<<(g.len-1));
for (zeroExpCount=0,n=0;n<count;n++)
{
/*
以下的代码得到一种'+'和'-'的组合,
类似于将n转化为二进制数,只不过,这里用'+'表示'0',用'-'表示'1',
*/
for (i=0;i<g.len-1;i++)
{
mask=(1 << i);
if ( (n & mask)==0 )
g.signArray[i]='+';
else
g.signArray[i]='-';
}
//计算表达式的结果
r=str2num(g.strTable[0].p,g.strTable[0].len);
for (i=0;i<g.len-1;i++)
{
// r2: 第二操作数字
r2=str2num(g.strTable[i+1].p,g.strTable[i+1].len);
if (g.signArray[i]=='+')
r+= r2;
else
r-= r2;
}
if (r==0)
{
//printfExpression(r);//如果想打印这个表达式,请打开这语句
zeroExpCount++;
}
}
return zeroExpCount;
}
//递归函数,得到所有数字切分的组合
// 参数level:已经切分出来的各个数的个数
// *pCount: 符合条件的表达式的个数
// n,数字的个数,
void getAllCombo(int n,int *pCount,int level)
{
static int ret;
char *p;
int i,totalLen,len;
for (totalLen=0,i=0;i<level;i++)
totalLen+=g.lenArray[i];
if (totalLen==n) //得到一种切分
{
g.len=level;
//-----计算strTable----
for (p=digArray,i=0;i<level;i++)
{
g.strTable[i].p=p;
g.strTable[i].len=g.lenArray[i];
p+=g.lenArray[i];
}
if (level>1) //得到一种有效的切分
*pCount+=check(); //检查可组成运算结果等于0的表达式的个数
}
else
{
for (i=1;i<=n-totalLen;i++)
{
g.lenArray[level]=i;
getAllCombo(n,pCount,level+1);//求下一段切分
}
}
}
int ResultIsZero(int n)
{
int r=0;
getAllCombo(n,&r,0);
return r;
}
int main(int argc, char* argv[])
{
int count,n;
printf("plese input a num n(2<=n<=9)");
scanf("%d",&n);
if (n<2 || n>9)
return 0;
count=ResultIsZero(n);
printf("总共有%d种符合条件的表达式\n",count);
return 0;
}
我来回复