读书人

ACM一道竞赛题解决思路

发布时间: 2012-02-06 15:52:44 作者: rapoo

ACM一道竞赛题
内容是这样的 由于是鸟文 我也看不太懂
给一个数M,则有自然数1~N前面加上符号运算得到M,求出最小的N并输出,例如:M=12,-1+2+3+4+5+6-7=12 输出7;

[解决办法]
完整代码,编译通过,写得很粗糙
..................................
#include <stdlib.h>
#include <stdio.h>
int sss(int num,int n)
{
if(n> 0)
return num*(sss(num,n-1));
else
return 1;
}

int get(int i,int num,int *sum)
{

int nLen,j,mm;
mm = strlen(sum);
sum=(int*)realloc(sum,sss(2,i)*sizeof(int));
nLen=sss(2,i);
mm=strlen(sum);
j=0;
for(;j <nLen/2;j++)
{
if(sum[j]-i==num)
{

printf( "result:%d\n ",i);
//break;
return 0;
}
else
sum[j+nLen/2]=sum[j]-i;

}
j=0;
for(;j <nLen/2;j++)
{

if(sum[j]+i==num)
{
printf( "result:%d\n ",i);
return 0;
}
else
sum[j] = sum[j]+i;
}

return get(i+1,num,sum);
}
int main()
{

int *sum;
int num;

while(1){
sum=(int*)malloc(1*sizeof(int));
sum[0] = 0;
printf( "input the num\n ");
scanf( "%d ",&num);
get(1,num,sum);
free(sum);
}
return 0;
}
[解决办法]
用动态规划不就可以了??下面用一段伪码给出算法,非Pascal也非C,理解就可以了嘛。
开一个数组bool a[1..maxN][-maxM..maxM];
其中a[i][j]表示用前i个数是否可以凑出j
初始化令a[1][-1]=a[1][1]=true;其余的全为false
然后这样:
i=2;
do{
for(int j=-maxM;j <=maxM;j++) if(a[i-1][j])
{
if(abs(j+i) <=maxM) a[i][j+i]=true;
if(abs(j-i) <=maxM) a[i][j-1]=true;
}
}while(a[i][M]==false);
当然了,这段代码很烂,可以大大的优化,算法如此
[解决办法]
有个比较简单的算法:
#include <iostream>
#include <cmath>

using namespace std;

int main()
{
int M,n,distance;

cout < < "Please input the valua of M: " < < endl;
cin > > M;

n = (int)(( sqrt(8 * M) - 1 ) / 2); // < <== n(n+1)/2 > = M
if( n * (n+1)/2 < M )
n ++;
distance = n * ( n + 1) / 2 - M;
while(distance % 2)
{
n ++;
distance += n;
}
cout < < n < < endl;

return 0;
}

符合时间和空间要求吗?
[解决办法]
还想问一下,你说的 "符号 "只包括 + . - 吧?

读书人网 >C++

热点推荐