文章目录
总述
这道的题目主要涉及的是DFS思想,给出求解过程的同时也将另一道经典DFS+剪枝问题-------八皇后问题给出了求解过程。
题目一:选数问题
原题叙述
Given n positive numbers, ZJM can select exactly K of them that sums to S. Now ZJM wonders how many ways to get it!
INPUT
The first line, an integer T<=100, indicates the number of test cases. For each case, there are two lines. The first line, three integers indicate n, K and S. The second line, n integers indicate the positive numbers.
OUTPUT
For each case, an integer indicate the answer in a independent line.
输入样例
1
10 3 10
1 2 3 4 5 6 7 8 9 10
输出样例
4
题目重述
题意比较简单,每次输入n个数字,从这T个数字的输入样例里面,选择K个数字(每个数字只能选择一次),使他们的和相加等于一个值S,求解一共有多少种这种组合的情况。
整个求解过程共执行T次,即对上述的求解过程执行T次。
解题思路
思路概述
DFS思想的板子题,使用一个数组来存储每一个点是否被访问过,在DFS过程中做如下的一些处理:(注:已选个数chosen_num,已选值的总和chosen_value,个数限值K,目的值S)
情况 | 采取的操作 |
---|---|
chosen_num==K && chosen_value==S | 组合个数+1 |
chosen_num<K && chosen_value>=S | 剪枝丢弃 |
chosen_num<K&& chosen_value<S | 向下进行DFS |
采用这种策略就可以将所有情况枚举出来
数据存储
使用
int store[20];
来存储每个点的访问情况,初始化将所有点置为0,DFS的过程中如果访问过就置为1
要注意的是:继续向下DFS的部分,如果将数字a加入到选择的数中,store[a]置为1后,在完成向下DFS的递归之后,将store[a]重置为0,这样可以保证在同一层选择数值时,store数组中的访问情况是完全相同的。
代码如下:
for(int i=begin;i<positive_number;i++)
{
if(store[i]==0)
{
store[i]=1;
dfs(number+1,addtion+store_number[i],i+1);
}
store[i]=0;//保证同层选择新数时,访问数组store[]情况完全一致
}
题目一总结
一道比较简单的Dfs板子题,但是要注意的是,如果在一次向下dfs后不添加访问数组重置的操作,会导致dfs过程出现较大的问题,在手写时在此处出现了错误,导致调试了几次才成功accept。
题目一改进点
暂无
题目一源码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int store_number[20];
int store[20];//存放每个点是否被访问过
int positive_number=0;//可供选择的数字个数
int add_number=0;//累计的数字个数
int num_addition=0;//累计的数字和
int sum_kind=0;//组合种类的个数
void dfs(int number,int addtion,int begin)
{
if(number==add_number && addtion==num_addition)
{
sum_kind++;
}
else if(number<add_number)
{
if(addtion>=num_addition)
return;
else
{