第八周算法题整理【动态规划,dfs】

题目:

A–三值排序

排序是一种很频繁的计算任务。一个实际的例子是,当我们给某项竞赛的优胜者按金银铜牌排序的时候。在这个任务中可能的值只有三种1,2和3。我们用交换的方法把他排成升序的。
写一个程序计算出,计算出的一个包括1、2、3三种值的数字序列,排成升序所需的最少交换次数。
输入第1行为类别的数量N(1≤N≤1000)
输入第2行到第N+1行,每行包括一个数字(1或2或3)。
输出包含一行,为排成升序所需的最少交换次数。

Sample Input

9
2
2
1
3
3
3
2
3
1

Sample Output

4

思路:
首先分析,无论交换前的数据如何,交换后一定可以分为三部分,第一部分是数据“1”,第二部分是数据“2”,第三部分是数据“3”,由于“1”永远在最前面,所以我门可以先固定第一部分,然后讨论第二、三部分
(1)首先找出数据中 “1”的个数sum1,即完成第一部分排序需要的步数
(2)然后要做的就只有 将第二部分中的“3”交换到第三部分、或者将第三部分的“2”交换到第二部分,分别记为sum2和sum3
(3)取sum1+max(sum2,sum3),至于为什么要取sum2和sum3之间的最大值,是因为如果取最小值,那么必定会有“2”遗留在第三部分或者“3”遗留在第二部分,取决于两者到底谁小

思路写出来挺繁琐的但不难理解,直接上代码:

#include <stdio.h>
#include <string.h>
int a[1001], cnt[4];
 
int main(void)
{
    int n, i;
    scanf("%d",&n);
    
   	for(i = 1; i <= n; i++) 
	{
	    scanf("%d", &a[i]);
	    cnt[a[i]]++;
	}
	 
	int sum1 = 0, sum2 = 0, sum3 = 0;
	
	for(i = 1; i <= cnt[1]; i++)
	{
		 if(a[i] != 1)
	        sum1++;
	}
	       
	for(i = cnt[1] + 1; i <= cnt[1] + cnt[2]; i++)
	{
		if(a[i] == 3)
	    	sum2++;
	}
	            
	for(i = cnt[1] + cnt[2] + 1; i <= n; i++)
	{
	    if(a[i] == 2)
	    	sum3++;    	
	}
	            
	 
	printf("%d\n", sum1 + (sum2 > sum3 ? sum2 : sum3));

    return 0;
}

B–自然数拆分

对于任意大于 1的自然数 n,总是可以拆分成若干个小于 n的自然数之和。
现请你编写程序求出 n 的所有拆分。
输入格式:
输入文件共一行,包含一个自然数,即要拆分的自然数 n(1≤n≤20)。
输出格式:
输出文件有若干行,每行包含一个等式,即代表一种可行的拆分(格式与顺序参见样例)。

Sample Input

5

Sample Output

5=1+1+1+1+1
5=1+1+1+2
5=1+1+3
5=1+2+2
5=1+4
5=2+3

思路:待补全

代码:

#include<stdio.h>
int n;
int a[25];

void dfs(int sum,int len,int start)
{
	if(n==sum)
	{
		printf("%d=%d",n,a[0]);
		for(int i=1;i<len;i++)
		{
			printf("+%d",a[i]);
		 } 
		 printf("\n");
		 return ;
	}
	
	for(int i=1;i<n;i++)
	{
		if(sum+i<=n && i>=start)
		{
			a[len++]=i;
			dfs(sum+i,len,i);
			len--;
		}
	}
}
int main(void)
{
	scanf("%d",&n);
	
	dfs(0,0,1);

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值