CSP-homework Week3 ProblemA DFS两题--选数问题和八皇后问题详解(C++)

本文详细介绍了使用DFS解决CSP竞赛中的两个问题:选数问题和八皇后问题。通过C++实现,解析了题目要求,提供了解题思路和代码实现,强调了在DFS过程中数据存储和状态重置的重要性。
摘要由CSDN通过智能技术生成

总述

这道的题目主要涉及的是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
       {
   
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值