NYOJ 1058 部分和问题(经典题目dfs)

部分和问题

描述

给定整数a1、a2、…….an,判断是否可以从中选出若干数,使它们的和恰好为K。

输入

首先,n和k,n表示数的个数,k表示数的和。

接着一行n个数。

(1<=n<=20,保证不超int范围)

输出

如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”

样例输入

4 13
1 2 4 7

样例输出

YES
2 4 7

题目分析:

这是一道经典的dfs问题,好多公司也用它做过面试题,我们定义函数dfs(k,i):对于组成k的几个数,有两种方法,

一、使用第i个值,下一步搜索dfs(k-a[i],i+1);

二、不适用第i个值,搜索dfs(k,i+1)

if(k==0)证明找到了解,return;

return的还有另外一种可能,就是搜索到第N+1个还使k=0,也要返回。

AC代码:

/**
  *@xiaoran
  *dfs
  */
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cctype>
#include<cmath>

#define LOCAL

#define LL long long
using namespace std;
int n,k,a[22],b[22],ok;
void dfs(int k,int i){
    //已经找到解或者已经到达数组尾部返回,注意此时到n+1
    if(ok||i==n+1) return ;
    //找到了解
    if(k==0){
        cout<<"YES"<<endl;
        for(int i=0;i<n;i++){
            if(b[i]==1){
                cout<<a[i]<<" ";
            }
        }
        cout<<endl;
        ok=1;
        return;
    }
    //if(k<0) return ;
    if(b[i]==0&&k-a[i]>=0){//没有使用
        b[i]=1;//记录使用的值,便于输出
        dfs(k-a[i],i+1);//使用第i个值,进行搜索
        b[i]=0;
    }
    dfs(k,i+1);//不使用第i个值进行搜索

}

int main()
{
    /*
    #ifdef LOCAL
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
    #endif
    */
    while(cin>>n>>k){
        memset(b,0,sizeof(b));
        ok=0;
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        dfs(k,0);
        if(ok==0) cout<<"NO"<<endl;
    }

    return 0;
}
时间: 2024-08-24 21:19:09

NYOJ 1058 部分和问题(经典题目dfs)的相关文章

NYOJ 1058 部分和问题 【DFS】

部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先,n和k,n表示数的个数,k表示数的和. 接着一行n个数. (1<=n<=20,保证不超int范围) 输出 如果和恰好可以为k,输出"YES",并按输入顺序依次输出是由哪几个数的和组成,否则"NO" 样例输入 4 13 1 2 4 7 样例输出 YES 2 4 7 简

nyoj 1058部分和问题(DFS)

部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先,n和k,n表示数的个数,k表示数的和.接着一行n个数.(1<=n<=20,保证不超int范围) 输出 如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO” 样例输入 4 13 1 2 4 7 样例输出 YES 2 4 7 #include<cstdio>

nyoj 1058部分和问题

部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先,n和k,n表示数的个数,k表示数的和.接着一行n个数.(1<=n<=20,保证不超int范围) 输出 如果和恰好可以为k,输出"YES",并按输入顺序依次输出是由哪几个数的和组成,否则"NO" 样例输入 4 13 1 2 4 7 样例输出 YES 2 4 7 #in

nyist oj 1058 部分和问题 (DFS搜索)

部分和问题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先,n和k,n表示数的个数,k表示数的和. 接着一行n个数. (1<=n<=20,保证不超int范围) 输出 如果和恰好可以为k,输出"YES",并按输入顺序依次输出是由哪几个数的和组成,否则"NO" 样例输入 4 13 1 2 4 7 样例输出 YES 2 4 7 来

NYOJ 298-点的变换(经典矩阵解决点平移、缩放、翻转和旋转)

题目地址:NYOJ 298 思路:该题如果用对每个点模拟的操作,时间复杂度为O(n+m),结果肯定超时.然而利用矩阵乘法可以在O(m)的时间内把所有的操作合并为一个矩阵,然后每个点与该矩阵相乘可以得出最终的位置. PS:十个利用矩阵乘法解决的经典题目 超级详细. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream&

Nyoj 吝啬的国度(图论&amp;&amp;双DFS)

描述在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号城市(假设你不走重复的路). 输入 第一行输入一个整数M表示测试数据共有M(1<=M<=5)组每组测试数据的第一行输入一个正整数N(1<=N<=100000)和一个正整数S(1<=S<=100000),N表示城市的总个数,S表示参观者所在城市的编号随后的N-1行,每行有两个正整数a,b

矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

https://www.vijos.org/p/1067 很容易推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵,其中右上角的(k-1)*(k-1)的矩阵是单位矩阵,第k行的每个数分别对应f[n-1],f[n-2],,f[n-k]的系数.然后构造一个k*1的矩阵,它的第i行代表f[i],是经过直接递推得到的.设ans[][]是第一个矩阵的n-k次幂乘上第二个矩阵,f[n]就是ans[k][1]. 注意:用__int64 #in

学习心得:《十个利用矩阵乘法解决的经典题目》from Matrix67

本文来自:http://www.matrix67.com/blog/archives/tag/poj大牛的博文学习学习 节选如下部分:矩阵乘法的两个重要性质:一,矩阵乘法不满足交换律:二,矩阵乘法满足结合律经典题目1 给定n个点,m个操作,构造O(m+n)的算法输出m个操作后各点的位置.操作有平移.缩放.翻转和旋转    这 里的操作是对所有点同时进行的.其中翻转是以坐标轴为对称轴进行翻转(两种情况),旋转则以原点为中心.如果对每个点分别进行模拟,那么m个操作总共耗时 O(mn).利用矩阵乘法可

十个利用矩阵乘法解决的经典题目

转载自    Matrix67: The Aha Moments 好像目前还没有这方面题目的总结.这几天连续看到四个问这类题目的人,今天在这里简单写一下.这里我们不介绍其它有关矩阵的知识,只介绍矩阵乘法和相关性质.    不要以为数学中的矩阵也是黑色屏幕上不断变化的绿色字符.在数学中,一个矩阵说穿了就是一个二维数组.一个n行m列的矩阵可以乘以一个m行p列的矩阵,得到的结果是一个n行p列的矩阵,其中的第i行第j列位置上的数等于前一个矩阵第i行上的m个数与后一个矩阵第j列上的m个数对应相乘后所有m个