省赛训练之递归(三)

今天学了递归,我们做的是poj上的2083:这道题用的是递归的方法

   思路:后一个图形是基于前一个图形而成的。

  • If using B(n - 1) to represent the box fractal of degree n - 1, then a box fractal of degree n is defined recursively as following
          B(n - 1)        B(n - 1)
    
                  B(n - 1)
    
          B(n - 1)        B(n - 1)

       方法:递归的方法,除了n==1时的出口是一个:"X",后面的都是在不同的5个位置上放置k个x,它们之间的距离是pow(3,(n-1));

                

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    char a[800][800];//七个的时候用到了a[729][729]所以,我们可以将它控制为a[800][800];
    int n;
    void image(int x,int y,int n){//表示以(x,y)为起点的n度。
    	int l;
    	if(n==1)
    		a[x][y]='X';
    	else{
    		l = pow(3,n-2);
    		image(x,y,n-1);
    		image(x+l,y+l,n-1);
    		image(x+2*l,y,n-1);
    		image(x,y+2*l,n-1);
    		image(x+2*l,y+2*l,n-1);
    	}
    }
    int main(){
    	int i,j,l;
    	while(scanf("%d",&n)!=EOF){
    		if(n==-1)
    			break;
    		memset(a,' ',sizeof(a));//先全部清空,赋值为空格。
    		image(0,0,n);
    		l=pow(3,n-1);
    		for(i=0;i<l;i++){
    			for(j=0;j<l;j++){
    				printf("%c",a[i][j]);
    			}
    			printf("\n");
    		}
    		printf("-\n");
    	}
    }


     

    2、今天的悬念:poj1011木棒问题

         思路:1、把所有的木棒的长度从大到小排列,组合时先使用比较长的木棍。    2、木棒的长度一定是大于等于最长木棍的长度并且小于等于所有木棍长度的和。   3、木棒的长度一定是所有木棍长度的和的约数。    4、在某一个木棒的组合的过程中,对于当前的木棍,如果现在使用的a[i-1]是没有被组合并且a[i]==a[i-1],那么不用考虑a[i]。5、如果此次是在尝试第i个木棒的第一段,假设a[j]为当前可以被使用的最长的木棍,如果此次组合失败。直接退出搜索,即退回到对第i-1个木棒的搜索。试想:失败说明现在使用a[j]都是不可行的。因为以后再处理a[j]时可使用的木棍的子集,在更多木棍选择的情况下都不能组合成功,那么,在更少木棍选择的情况下一定不能组合成功。

  • #include<stdio.h>
    #include<string.h>
    int n,a[100],flag[100],sum,k;//k表示因数
    int cmp(const void *a,const void *b){
    	return *(int *)b - *(int *)a;//从大到小进行排序
    }
    int search(int now,int start,int time){//now 表示现在的剩余量,start 表示开始的木棒,time 表示符合的次数
    	int i,j,sign=-1;
    	if(time*k==sum)	return 1;
    	for(i=start;i<n;i++){
    		if(flag[i]||a[i]==sign)//剪枝flag[i]==1:表示使用过,sign:表示不可以使用的。
    			continue;
    		if(a[i]+now==k){
    			flag[i]=1;
    			if(search(0,0,time+1)) return 1;
    			sign = a[i];//说明这个值不能使用
    			flag[i]=0;
    			return 0;
    		}
    		else if(a[i]+now<k){
    			flag[i]=1;
    			if(search(now+a[i],i+1,time))
    				return 1;
    				flag[i]=0;
    			if(now ==0)
    				return 0;
    		}
    	}
    		return 0;
    }
    int main(){
    	int i,j;
    	while(scanf("%d",&n)!=EOF){
    		if(n==0)
    			break;
    		sum = 0;
    		for(i=0;i<n;i++){
    			scanf("%d",&a[i]);
    			sum = sum +a[i];//木棍总长
    		}
    		qsort(a,n,sizeof(int),cmp);//排序
    		for(k=a[0];k<sum;k++){
    			if(sum%k!=0)
    				continue;
    			memset(flag,0,sizeof(flag));//清零
    			if(search(0,0,0))
    				break;
    		}
    		printf("%d\n",k);
    	//	for(i=0;i<n;i++)
    	//		printf("%d ",a[i]);
    	}
    }

    3、poj-->1504:

    思路:这道题是将数字反转过来以后,例如:305 794:求解的过程就是:305-->503;794-->497;按位相加以后得到的数是1000,再将其反转,反转过后就是1。

    方法:通过字符串反转。

     这道题如果不用大数做,就比较简单。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    int reserve(int x){
    	int a[100],i=0,k,j,y=0;
    	memset(a,0,sizeof(a));
    	while(x>0){
    		a[i] = x%10;
    		x = x/10;
    		i++;
    	}
    	for(k=0;k<i;k++){
    		y = y+a[k]*pow(10,i-k-1);
    	}
    //	printf("%d",y);
    	return y;
    }
    int main(){
    	int sum,n,i,p,q,j,T,a,b;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d",&a,&b);
    		p = reserve(a);
    		q = reserve(b);
    		sum = p+q;
    		printf("%d\n",reserve(sum));
    	}
    }


     

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值