#include<iostream> #include<vector> using namespace std; void help(int n, int m, vector<int>& v, int beg) { //if (beg>n) return; if (m == 0) { for (int i = 0; i<v.size(); i++) { i == 0 ? cout << v[i] : cout << " " << v[i]; } cout << endl; } for (int i = beg; i <= n&&i <= m; i++) { v.push_back(i); help(n, m - i, v, i + 1); v.pop_back(); } } int main() { int n, m; while (cin >> n >> m) { vector<int>v; help(n, m, v, 1); } }
代码写的屎一样
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
//常量区
int n, m, A[200];
vector<string> vec;
//函数区
void solve(int pos, int cnt, int num){
if(cnt == num){
int sum = 0;
for(int i = 1; i <= n; i++)
if(A[i] == 1) sum += i;
if(sum == m){
string tmp = "";
for(int i = 1; i <= n; i++){
if(A[i] == 1) {char c = '0' + i; tmp = tmp + c;}
}
vec.push_back(tmp);
}
return;
}
if(pos == n + 1) return;
if(!A[pos]){
A[pos] = 1;
solve(pos + 1, cnt + 1, num);
A[pos] = 0;
}
solve(pos + 1, cnt, num);
}
int cmp(string a,string b){
return a.compare(b)<0;
}
void show(){
int size = vec.size();
sort(vec.begin(), vec.end(), cmp);
for(int i = 0; i < size; i++){
for(int j = 0; j < vec[i].length(); j++){
if(j == 0) {printf("%d", vec[i][j] - '0');}
else printf(" %d", vec[i][j] - '0');
}
printf("\n");
}
}
//main函数
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++){
memset(A, 0, sizeof(A));
solve(1, 0, i);
}
show();
return 0;
}
/*
5 5
*/
var readline = require('readline') const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) rl.on('line', function(line) { var tokens = line.split(' ') var sumsArr = [] findSumArr(parseInt(tokens[0]), parseInt(tokens[1]), [], sumsArr) sumsArr.sort().forEach(function(item) { console.log(item); }) }) function findSumArr(n, m, sumArr, sumsArr) { if(m < 1) {//m===0 sumsArr.push(sumArr.sort().join(' ')) return } if(n < 1) { return } // 如果n大于m,则将n赋值为m(大于m的值无用 if(n > m) { n = m } // 注意:这里不能直接使用 tmpArr=sumArr var tmpArr = [] sumArr.forEach(function(item) { tmpArr.push(item) }) // 1. 不将n放入数组 findSumArr(n-1, m, sumArr, sumsArr) // 2. 将n放入数组 tmpArr.push(n) findSumArr(n-1, m-n, tmpArr, sumsArr) }
def rec(i, m, res): ans = [] for j in range(i, n+1): if j == m: ans.extend([x+[j] for x in res]) break if j < m: ans.extend(rec(j+1, m-j, [x+[j] for x in res])) else: continue return ans if __name__ == '__main__': n, m = [int(x) for x in input().split()] ans = rec(1, m, [[]]) for a in ans: print(' '.join([str(x) for x in a]))
#include <iostream>
#include <algorithm>
using namespace std;
void slove(int now, int pre) {
cout << pre << " ";
if(now - (pre + 1) > (pre + 1)) {
for(int i = 1; now - (pre + i) > (pre + i); i++) {
if(i != 1) cout << pre << " ";
slove(now - (pre + i), pre + i);
}
} else {
cout << now << endl;
}
}
int main()
{
int n, m;
cin >> n >> m;
int e = min(n, m / 2);
for(int i = 1; i <= e; i++) {
if(m - i <= i) continue;
slove(m - i, i);
}
if(n >= m) cout << m << endl;
return 0;
}
/**
5 5
3 7
**/
其实就是回溯算法,把所有的状态都列出来,利用简单的剪枝方法,提高效率。具体代码里都有注释
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> v;
void find_ans(vector<int> ret, int cur_pos, int n, int cur_sum, int sum) {
if (cur_pos >= n) return ;
cur_sum += v[cur_pos];
ret.push_back(v[cur_pos]);
if (cur_sum == sum) {
for (int i = 0; i < ret.size() - 1; ++i) {
cout << ret[i] << " ";
}
cout << ret[ret.size() - 1];
cout << endl;
return ;
} else if (cur_sum > sum) { // 大于sum,就没必要再继续往下了,剪枝操作
return ;
}
// 把当前的下标位置的值放进去,继续下一个位置
find_ans(ret, cur_pos+1, n, cur_sum, sum);
// 不要当前值,从下一个位置搜索,意思大概就是不从1开始找了,从2开始找
vector<int>::iterator it = ret.end();
--it;
ret.erase(it);
find_ans(ret, cur_pos+1, n, cur_sum - v[cur_pos], sum);
// 总体思想就是当前位置的数是要还是不要的事情,列出来所有的可能,挨个输出就行了
}
int main() {
int n, num;
cin >> n >> num;
for (int i = 0; i < n; ++i) {
v.push_back(i+1);
}
// 因为如果n大于num的话,那么num后面的数字肯定不需要再考虑了,所以我们只需要考虑从1~num之间的可能组合就行了
if (n >= num) n = num;
vector<int> ret;
int sum = 0;
// 利用递归的方法来做,0是当前位置,n是最大下标,sum是当前和,num就是要求的结果
find_ans(ret,0,n,sum,num);
return 0;
}
#include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; int main() { int m = 0; int n = 0; cin >> n >> m; int bit = 1 << n; int count = 0; int current = 0; vector<string> vec; while (current++ < bit) { int sum = 0; string s; for (int i = 0; i < n; i++) { if ((current >> i) & 1) { sum = sum + i + 1; s = s + to_string(i+1); } } if (sum == m) { count++; vec.push_back(s); } } sort(vec.begin(), vec.end()); for (int i = 0; i < vec.size(); i++) { for (int j = 0; j < vec[i].size() - 1; j++) { cout << vec[i][j] << ' '; } cout << vec[i][vec[i].size() - 1] << endl; } }
// 深度优先遍历 import java.util.*; public class Main { public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); int m = sc.nextInt(); ArrayList aList = new ArrayList<Integer>(); for(int i=1;i<=n;i++){ aList.add(i); count(m, i, i,n,aList); aList.remove(aList.size()-1); } } } public static void count(int m, int sum, int currentVal, int n, ArrayList aList){ if(sum>m)return; if(sum==m){ StringBuilder sb = new StringBuilder(); Iterator it = aList.iterator(); while(it.hasNext()){ sb.append(it.next() + " "); } System.out.println(sb.toString().trim()); }else{ for(int i=currentVal+1;i<=n;i++){ aList.add(i); count(m, sum+i, i, n,aList); aList.remove(aList.size()-1); } } } }
process.stdin.resume(); process.stdin.setEncoding('ascii'); var input=''; process.stdin.on('data', function(data){ input+=data; var inputArr=input.split(" "), n=inputArr[0], m=inputArr[1], result=[]; var allComb=getAllComb(n); //求出1至n所有的组合 allComb.forEach(function(ele){ //筛选出所有和为m的组合 if(ele.reduce(function(a,b){returna+b})==m){ result.push(ele.join(" ")) } }); var res=[]; for(var i=0;i<result.length;i++){ //调整至满足要求的顺序 res[i]=result[result.length-i-1]; } console.log(res.join("\n")); //换行输出所有结果 function getAllComb(n){ //用二进制数表示所有可能的组合,再用下标的方法求出所有组合 var max=Math.pow(2,n), arr=[], res=[]; for(var i=1;i<=n;i++){ arr.push(i); } for(var i=1;i<max;i++){ var temp=i.toString(2), size=temp.length, subRes=[]; if(size<n){for(var j=0;j<n-size;j++){temp="0"+temp}} //补足二进制数temp前的空位 for(var k=0;k<arr.length;k++){ if(temp[k]==true){ subRes.push(arr[k]) } } res.push(subRes); } return res; } });
#include <iostream> #include <vector> using namespace std; void dfs(int n, int m, vector<int>& v, int beg){ // m == 0 为递归结束条件. 此时 v 中可能已经包含了若干个元素了 //并且 v 中的内容就是一组结果. if(m == 0){ for(int i = 0; i < v.size(); ++i){ i == 0 ? cout << v[i] : cout << " " << v[i]; } cout << endl; } for(int i = beg; i <= n && i <= m; ++i){ // 以下几行代码是该题目的关键. 问题的转换. // 为了求 i -> n 有多少种情况和为 m, 则把问题转换为 // i + 1 -> n 有多少中情况和为 m - i v.push_back(i); dfs(n, m - i, v, i + 1); v.pop_back(); } } int main(){ int n,m; while(cin >> n >> m){ vector<int> v; dfs(n,m,v,1); } return 0; }
import itertools n, m = list(map(int, input().split(' '))) list1 = [] list2 = [] for i in range(1, n + 1): if i == m: list1.append(i) continue else: list2.append(i) list3 = [] for i in range(1, len(list2) + 1): iter = itertools.combinations(list2, i) list3.append(list(iter)) list4 = [] for i in list3: for j in i: if sum(j) == m: list4.append(j) list4.sort() for i in list4: for j, k in enumerate(i): if j == len(i) - 1: print(k) else: print(k, end=" ") if not list1: pass else: print(list1[0])
/*思路:实质就是暴力解决问题,将所有的情况枚举出来,然后删选出符合自己要求的结果 对于1,2,3....n的数中随便选出其中几个出来,只要和是m,就以字典序输出 其实就是取决于我对于每个数的取舍问题: 比如 对于数字 1 我只有两种策略:要或者不要 要的我用res记录下来,并且加到sum中 不要的我直接过(可参照下面代码) 对于数字 2 我也只有两种策略:要或者不要 依次类推.......... 最后的结束标志:就是我到最后一个数字 n 判定完成之后,看我的 sum 和 m 是否相等 相等就输出,然后结束这一个分支的递归 不相等就不输出,但是也要结束这个分支的递归 按照先要再不要的策略,最后输出的结果就是字典序。 */ import java.util.*; public class Main{ public static void main(String [] args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int m = sc.nextInt(); String res = "";//用来记录被选到的数 int sum = 0; //用来记录被选到数加起来的总和 int []num = new int[n]; int j =1; for(int i = 0;i < n;i++) num[i] = j++; process(num,m,res,sum,0); } public static void process(int[] num,int m,String res,int sum,int i){ if(i == num.length){ if(sum == m) //这里用trim()方法就是去除每个输出最后的一个空格 System.out.println(res.trim()); return; } //表示我将num[i]这个数选到了 process(num,m,res+num[i]+" ",sum+num[i],i+1); //表示我不要num[i]这个数 process(num,m,res,sum,i+1); } }
#include<stdio.h>
int n,c[10],k,i,m; void print(int i,int m,int k) { c[k]=i; if(i==m&&m<=n) { for(int j=1;j<k;j++) printf("%d ",c[j]); printf("%d\n",c[k]);//一种情况结束 } else { for(int j=i+1;j<=m-i;j++)//核心递归,使得左边数小于右边,并且能通过递归嵌套,找出子集数量2以上的和为M的情况 print(j,m-i,k+1); } } int main () { scanf("%d %d",&n,&m); for(i=1;i<=n;i++) print(i,m,1);//一种情况开始 }
#include <iostream> #include <vector> using namespace std; void Solve(int n, int m, vector<int> &v, int cnt) { if(m==0) { for(int i=0;i<v.size();i++) { if(i==v.size()-1) cout<<v[i]<<endl; else cout<<v[i]<<" "; } } for(int i=cnt;i<=m && i<=n;i++) { v.push_back(i); Solve(n,m-i,v,i+1); v.pop_back(); } } int main() { int n,m; while(cin>>n>>m) { vector<int> v; Solve(n,m,v,1); } return 0; }
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner; /** * Created by hongjing on 2017/9/10. */ public class Main { public static List sum(int n, int m){ List<Integer> result = new ArrayList<>(); Map<Integer, Integer> map = new HashMap<>(); for (int i = 1; i <= n; i++){ map.put(i, i); } for (int i = 1; i < m / 2 + 1; i++){ if (map.containsKey(m - i)){ result.add(i); result.add(m - i); } } if (n == m){ result.add(m); } return result; } public static void main(String[] args){ Scanner in = new Scanner(System.in); String line = in.nextLine(); String ta = null; if (in.hasNext()){ ta = in.nextLine(); } List<Integer> result = sum(Integer.parseInt(line), Integer.parseInt(ta)); int sum = result.size(); for (int i = 0; i < sum;){ //奇数个结果 if (i == sum - 1 && sum % 2 != 0){ System.out.println(result.get(i)); i ++; }else { System.out.println(result.get(i) + " "+ result.get(i + 1)); i += 2; } } } }
使用回溯法 import java.util.*; public class Main { static ArrayList<List<Integer>> res = new ArrayList<>(); public static void main(String[] args) { Scanner cin = new Scanner(System.in); int N = cin.nextInt(); int M = cin.nextInt(); List<Integer> list = new ArrayList<>(); //当n>m时,其实大于部分是不可能取到的 int min = N < M ? N : M; printList(min, M, 0, 1, list); //按照字典序排列 Collections.reverse(res); for (int i = 0; i < res.size(); i++) print(res.get(i)); } private static void printList(int N, int M, int m, int n, List<Integer> list) { if (m == M) { ArrayList<Integer> result = new ArrayList<Integer>(); result.addAll(list); res.add(result); return; } if (n > N || m > M) { return; } //不放入 printList(N, M, m, n + 1, list); //放入 list.add(Integer.valueOf(n)); printList(N, M, m + n, n + 1, list); //回溯 list.remove(Integer.valueOf(n)); } private static void print(List<Integer> list) { for (int i = 0; i < list.size(); i++) { if (i != 0) System.out.print(" "); System.out.print(list.get(i)); } System.out.println(); } }