换零钱,C语言换钱问题,2种解法,5种优化,动态规划+动态数组

 

 

换钱问题,C语言,2种解法,6种优化,动态规划+动态数组

新人第一次发帖,排版渣,见谅。

学c语言一个月,技术算法水平不高,如有问题请指出,感谢


题意:
给出n元,将n元换成由1、5、10、20、50、100面值组成的钱,求有多少兑换方法

1暴力,简单粗暴,把每种面值的情况都试一下,符合条件的自增,测试n=20结果大概1秒出来


#include
#include
int main()
{
	int n,m;
	while(scanf("%d",&n)!=EOF)
	{
		m=0;
    	for(int i1=0;i1<=n;++i1){
    	    for(int i2=0;i2<=n;++i2){
        	    for(int i3=0;i3<=n;++i3){
            	    for(int i4=0;i4<=n;++i4){
                	    for(int i5=0;i5<=n;++i5){
                    	    for(int i6=0;i6<=n;++i6){
                        		if(n==100*i6+50*i5+20*i4+10*i3+5*i2+i1){
                            	++m;
                            	//printf("方案%d:100元:%d张 50元:%d张 20元:%d张 10元:%d张 5元:%d张 1元:%d张\n",m,i6,i5,i4,i3,i2,i1);
							}
					   }
                   }
               }
           }
        }    
    }
    printf("%d\n",m);
	}
return 0;
}
2暴力,暴力的优化版,把剩余钱可能存在的面值的情况都试一下,符合条件的自增,测试n=200结果大概1秒出来
#include
int main()
{
	int n,m;
	while(scanf("%d",&n)!=EOF)
	{
		m=0;
    	for(int i1=0;i1<=n;++i1){
           	for(int i2=0;i2<=(n-i1)/5;++i2){
               	for(int i3=0;i3<=(n-i1-i2*5)/10;++i3){
                	for(int i4=0;i4<=(n-i1-i2*5-i3*10)/20;++i4){
                		for(int i5=0;i5<=(n-i1-i2*5-i3*10-i4*20)/50;++i5){
                 			for(int i6=0;i6<=(n-i1-i2*5-i3*10-i4*20-i5*50)/100;++i6){
                       			if(n==100*i6+50*i5+20*i4+10*i3+5*i2+i1){
                           			++m;
                           			//printf("方案%d:100元:%d张 50元:%d张 20元:%d张 10元:%d张 5元:%d张 1元:%d张\n",m,i6,i5,i4,i3,i2,i1);
								}
							}
                   	    }
               	    }
           	    }
       	    }	    
	    }
	    printf("%d\n",m);
	}
	return 0;
}

3动态规划,解释起来比较复杂,对每个面值可能的情况每次循环进行一次兑换的考虑,第一次考虑由1元组成的情况,
第二次循环考虑对1和5元组成的情况,第三次考虑由1元、5元和10元组成的情况,以此类推,
考虑6次,比如n=10时,第一次循环temp[0~9]=1,第二次循环temp[0~4]=之前的1,temp[5~9]=之前的1+1=2,
temp[10]=之前的2+1=3
#include 
int main()
{
	int a[6]={1,5,10,20,50,100},n;
	while(scanf("%d",&n)!=EOF)
	{
		int temp[10000]={0};
		temp[0]=1;
		for(int i=0;i<6;i++){
			for(int j=1;j<=n;j++){
				if(j>=a[i])
					temp[j]+=temp[j-a[i]];
			//printf("%d\n",temp[j]);
			}
		//	printf("\n");
		}
		printf("%d\n",temp[n]);
	}
	return 0;
}

4动态规划,在上一个基础上嵌套循环的j每次不必要从1开始,因为每次1~a[i]-1都是不符合后面的if条件的,
这部分是无用循环,所以在符合钱数大于下一次的面值a[i]的时候直接让j从a[i]开始循环,此时也省了后面的if判断条件,注释掉即可
#include 
int main()
{
	int a[6]={1,5,10,20,50,100},n;
	while(scanf("%d",&n)!=EOF)
	{
		int temp[10000]={0};
		temp[0]=1;
		for(int i=0;i<6;i++){
			for(int j=a[i];j<=n;j++){
			//	if(j>=a[i])
					temp[j]+=temp[j-a[i]];
			//printf("%d\n",temp[j]);
			}
		//	printf("\n");
		}
		printf("%d\n",temp[n]);
	}
	return 0;
}

5动态规划+动态数组
上面的算法都是在a[10000]内的,如果n>=10000的话,数组溢出,
如果把数组开大浪费内存空间,开小了n输入限制,所以采用动态数组的方式,n是多少就有n+1个数组

动态数组格式
#include //所需头文件
int *a;
int N;
scanf("%d", &N);//获取数组大小
a = (int *) malloc(N * sizeof(int));//分配空间
....
free(a);//释放内存


下面是代码

#include 
#include
int main()
{
	int a[6]={1,5,10,20,50,100},n;
	while(scanf("%d",&n)!=EOF)
	{
		int *temp=(int*)malloc(sizeof(int)*(n+1));//n+1防止下面temp[j]溢出
		temp[0]=1;
		for(int i=0;i<6;i++)
			for(int j=a[i];j<=n;j++)
					temp[j]+=temp[j-a[i]];
		printf("%d\n",temp[n]);
		free(temp);
	}
	return 0;
}
因为int范围-2~31到2~31,所以int最大2147483647,对应本题到n为4094或4095,4096超int范围

6动态规划+动态数组+扩大应用范围
既然动态数组,那么改变数据类型long long,可以求更大的n对应的结果
#include 
#include
int main()
{
	int a[6]={1,5,10,20,50,100},n;
	while(scanf("%d",&n)!=EOF)
	{
		long long *temp=(long long*)malloc(sizeof(long long)*(n+1));
		temp[0]=1;
		for(int i=0;i<6;i++)
			for(int j=a[i];j<=n;j++)
					temp[j]+=temp[j-a[i]];
		printf("%lld\n",temp[n]);
		free(temp);
	}
	return 0;
}

 

 

 

你可能感兴趣的:(兑换钱,动态规划+动态数组)