现在有一个小盒子,能放N个小球(N<=8),现在要从这些小球里挑出N个小球,放满盒子。
想知道有哪些挑选方式。注:每种颜色的小球之间没有差别。
请按数字递增顺序输出挑选小球的所有方式。
如有3种颜色,每种颜色小球的个数分别为a:1,b:2,c:3,挑出3个小球的挑法有:
003,012,021,102,111,120
第一行两个数字K N,分别表示小球种类数目和挑选的小球个数
第二行开始为每种小球的数目,共K行数据
输出所有可行的挑选方案,按升序排列
3 3 1 2 3
003 012 021 102 111 120
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.TreeSet;
public class Main {
private static TreeSet<String> results = new TreeSet<>();
private static int[] colorfulBalls;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] params = br.readLine().split(" ");
int k = Integer.parseInt(params[0]), n = Integer.parseInt(params[1]);
colorfulBalls = new int[k];
int[] remainBalls = new int[k];
for(int i = 0; i < k; i++) {
colorfulBalls[i] = Integer.parseInt(br.readLine());
remainBalls[i] = colorfulBalls[i];
}
dfs(remainBalls, n, 0);
for(String result: results){
System.out.println(result);
}
}
private static void dfs(int[] remainBalls, int rest, int depth) {
if(rest == 0){ // 不需要球了,添加一个答案
StringBuilder sb = new StringBuilder();
for(int i = 0; i < remainBalls.length; i++){
sb.append(colorfulBalls[i] - remainBalls[i]);
}
results.add(sb.toString());
}
if(rest > 0){
for(int i = depth; i < remainBalls.length; i++){
if(remainBalls[i] > 0){ // 第i个颜色还有球的时候就拿一个
remainBalls[i] --;
dfs(remainBalls, rest - 1, i);
remainBalls[i] ++; // 回溯
}
}
}
}
} import java.util.*;
/**
* 回溯算法
*/
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int k = scan.nextInt();
int n = scan.nextInt();
Map<Integer, Integer> nums = new HashMap<>();
for (int i = 0; i < k; i++)
nums.put(i, scan.nextInt());
scan.close();
traverse(new StringBuilder(), nums, 0, n);
for (String s : result)
System.out.println(s);
}
static List<String> result = new ArrayList<>();
static int ballUsed = 0; //记录已使用小球数量
static boolean flag = false;
static void traverse(StringBuilder res, Map<Integer, Integer> nums, int k, int n) {
if (ballUsed > n) {
flag = true;
return;
}
if (k == nums.size()) {
if (ballUsed == n)
result.add(res.toString());
return;
}
for (int i = 0; i <= nums.get(k); i++) {
res.append(i);
ballUsed += i;
traverse(res, nums, k + 1, n);
ballUsed -= i;
res.deleteCharAt(res.length() - 1);
if (flag) { //剪枝,如果已使用小球超过总数n,则不再回溯
flag = false;
return;
}
}
}
} import sys
K, N = list(map(int, sys.stdin.readline().split()))
def backtrace(i, my_dic, cnt, res, s):
if i == K and cnt == N:
res.append(''.join(s))
elif i < K:
for use in range(my_dic[i]+1):
if use <= N - cnt:
s.append(str(use))
backtrace(i+1, my_dic, cnt+use, res, s)
s.pop()
else:
break
if __name__ == '__main__':
my_dic = {}
for i in range(K):
my_dic[i] = int(sys.stdin.readline().strip())
res = []
backtrace(0, my_dic, 0, res, [])
for r in res:
print(r) # coding=utf-8 import sys a = [0]*11 ans = [0]*11 k,n=0,0 def Print(k, ans): res = '' for i in range(k): res += str(ans[i]) print(res) def fun(i, n): # i可以认为是球类比的编号,ans[i]就是结果中,i类球放几个 if n==0: # n=0就是递归结束了,要放的球都安排好了~ Print(k, ans) return if n<0 or k==i: return for j in range(a[i]+1): # a[i]+1就是j可以取0~a[i] # 即j表示这类球放几个 ans[i] = j fun(i+1, n-j) # i+1是移动下,考虑放下一类球了~ ans[i] = 0 # 没遍历到的ans位就是放0个球 try: while True: line1 = sys.stdin.readline().strip() l = list(map(int, line1.split())) k = l[0] # 球共所少类 n = l[-1] # 共需要n个球 nums = sys.stdin.readlines() # a数组,index为球的类,index上的value为这类球有的数量 a = [int(v.strip()) for v in nums] fun(0, n) except: pass
/*C++,AC百分之八十,测试用例运行时间:3ms,内存占用:376k,
*采用迭代递归,有大佬看的话麻烦指点优化一下,谢谢~~~
*/
#include <iostream>
#include <vector>~~
#include<iterator>
using namespace std;
void demo(vector< vector<int> > *v, vector<int> *v1, int n, int l, int sum)
{
if (l == n)
{
int sum1 = 0;
for (unsigned int j = 0; j < l; j++)
{
sum1 += v1->at(j);
}
if (sum1 == sum)
{
copy(v1->begin(), v1->end(), ostream_iterator<int>(cout));
cout << endl;
}
return;
}
for (unsigned int j = 0; j < v->at(l).size(); j++)
{
v1->at(l) = v->at(l).at(j);
demo(v, v1, n, l + 1, sum);
}
}
int main()
{
int n = 0;
int sum = 0;
cin >> n >> sum;
vector< vector<int> > v_int(n);
for (int i = 0; i < n; i++)
{
int temp = 0;
cin >> temp;
for (int j = 0; j <= temp; j++)
{
v_int.at(i).push_back(j);
}
}
vector<int> temp1(n);
demo(&v_int, &temp1, n, 0, sum);
return 0;
} #include <iostream>
#include<vector>
#include<numeric>
using namespace std;
struct node{
int num;
vector<vector<int> > v;
};
int main(){
int K, N,Ki;
cin >> K >> N;
vector<node> ball(K);
for(int i=0;i<K;i++){
node p;
cin>>Ki;
ball[i].num=Ki;
}
if(K==1) cout<<N<<endl;
else {
vector<int> tmpv;
for(int i=0;i<=ball[0].num;i++) {
tmpv.push_back(i);
ball[0].v.push_back(tmpv);
tmpv.clear();
}
for(int i=1;i<K;i++){
for(int j=0;j<ball[i-1].v.size();j++){
for(int k=0;k<=ball[i].num;k++){
tmpv=ball[i-1].v[j];
tmpv.push_back(k);
if(i==K-1){
if(accumulate(tmpv.begin(),tmpv.end(),0)==N){
for(int l=0;l<tmpv.size();l++) cout<<tmpv[l];
cout<<endl;
}
}
else {
if(accumulate(tmpv.begin(),tmpv.end(),0)<=N) ball[i].v.push_back(tmpv);
}
tmpv.clear();
}
}
}
}
} #include<iostream>
(720)#include<string>
#include<iomanip>
using namespace std;
int box[10];
int kind, sum;
void jisuan(int num,int box_id,long long X)
{
long long M = 1;
if (num == 0)
{
return;
}
for (int q = 0; q < (kind - box_id) - 1; q++)
{
M = M * 10;
}
for (int i = 0; i <= box[box_id]; i++)
{
if (num == i)
{
cout << setfill('0') << setw(kind) << *right<< X + i * M<<endl;
}
if (i < num)
{
if (box_id != kind - 1)
jisuan(num - i, box_id + 1, X + i * M);
}
}
}
int main()
{
cin >> kind >> sum;
for (int i = 0; i < kind; i++)
{
cin >> box[i];
}
jisuan(sum,0,0);
} #include <bits/stdc++.h>
using namespace std;
int k,n;
vector<int> nums;
set<string > ret;
void dfs(int index,int len,string &ans){
if(len==n){
ret.insert(ans);return ;
}
for (int i=index;i>=0;i--){
if(nums[i]>0){
ans[i]++,nums[i]--;
dfs(i,len+1,ans);
nums[i]++,ans[i]--;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin>>k>>n;
int temp;
for (int i=0;i<k;i++){
cin>>temp;
nums.push_back(temp);
}
string ans(k,'0');
dfs(k-1,0,ans);
for (auto s:ret)
cout<<s<<endl;
}
import java.util.Scanner;
import java.util.List;
import java.util.LinkedList;
import java.lang.Math;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int k = sc.nextInt();
int n = sc.nextInt();
int[] nums = new int[k];
for(int i = 0;i < k; i++){
nums[i] = sc.nextInt();
}
List<String> result = new LinkedList<>();
help(result,n,0,nums,"");
result.forEach(System.out::println);
}
}
protected static void help(List<String> result,int target,int start,int[] nums,String s){
if(target == 0 && start == nums.length){
result.add(s);
return;
}
if(start == nums.length){
return;
}
for(int i = 0;i <= Math.min(target,nums[start]);i++){
// 取当前 target 和对应球的数量中的较小值。
help(result,target - i,start+1,nums,s+i);
}
}
} 用一个recursion可以解决,每次在每个位置放上可能的值,在最后检查该解是否符合题目要求(总和为n)
#include
#include
#include
#include
using namespace std;
void printVec(vector v)
{
for (auto x : v)
cout << x;
cout << endl;
}
void solve(vector temp, vector b, int index, int r)
{
if (index == temp.size())
{
if (r == 0)
printVec(temp);
return;
}
for (int i = 0; i <= min(b[index], r); i++)
{
temp[index] = i;
solve(temp, b, index + 1, r - i);
}
}
int main()
{
int k, n;
cin >> k >> n;
vector balls (k);
for (int i = 0; i < k; i++)
cin >> balls[i];
vector v (k, 0);
solve(v, balls, 0, n);
}
// 回溯
function two(kindN, selectN, arr) {
let ans = []
function backup(k, target, subans) {
if (target < 0) return
if (k == kindN && target == 0) {
ans.push([...subans]);
}
for (let i=0; i<=arr[k]; i++) {
subans.push(i);
backup(k+1, target-i, subans);
subans.pop();
}
}
backup(0, selectN, []);
return ans
}
var line;
while (line=readline()) {
let tmp = line.split(' ');
let K = parseInt(tmp[0]), T = parseInt(tmp[1]);
let Arr = [];
for (let i=0; i<K; i++) {
Arr.push(parseInt(readline()))
}
let ans = two(K, T, Arr);
for (let i=0; i<ans.length; i++) {
console.log(ans[i].join(''));
}
} #include <vector>
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int total = 0;
int k, n;
vector<int>num;
//@FUNCTION arrange 是安排每个颜色的球的个数
//@PARAM currentnum 是string类型的变量用来存放安排的结果,i是现在操作的第i种小球,current代表
//盒中当前已经放置的球,n表示盒中存放的最大数
void arrange(string& currentnum,int i,int ¤t,int n) {
if (n - current <= 0) {
currentnum = string(1, '0') + currentnum;
}
else if (num[i] - (n - current) > 0) {
currentnum = string(1, char(n - current + '0')) + currentnum;
current += (n - current);
}
else {
currentnum = string(1, char(num[i] + '0')) + currentnum;
current += num[i];
}
} //@FUNCTION dealCarry 处理进位,当前数的下一个数是将数的最后一位减1,加到上一位中。
//这里我采用的思想是来源于字典排序如何获取下一个序列。
//@PARAM N代表当前数的大小,index表示可以进的位。
bool dealCarry(string &N,int index) {
while (index>0&&N[index-1]-'0'+1>num[index-1]) {
--index;
}
if (index <= 0) {
return false;
}
int total_ = 0;
for (int i = index; i < N.size(); ++i) {
total_ += (N[i] - '0');
}
--total_;
string currentnum;
int current = 0;
for (int i = num.size() - 1; i >= index; --i) {
arrange(currentnum, i, current, total_);
}
N[index - 1] += 1;
N = string(N, 0, index) + currentnum;
return true;
}
//@FUNCTION permutation 是采用进位的方法获取下一个序列
bool permutation(string& N) {
int i = N.size()-1;
for (; i > 0; --i) {
if (N[i] != '0')break;
}
if (dealCarry(N, i)) {
return true;
}
return false;
}
int main() {
cin >> k >> n;
num = vector<int>(k, 0);
for (int i = 0; i < k; ++i) {
cin >> num[i];
total += num[i];
}
string currentnum;
int current = 0;
for (int i = k - 1; i >= 0; --i) {
arrange(currentnum,i, current,n);
}
if (current == n) {
cout << currentnum << endl;
while (permutation(currentnum)) {
cout << currentnum << endl;
}
}
return 0;
} c++ dfs AC100
#include
(849)#include
using namespace std;
void dfs(vector a, int n, int index, vector res)
{
if (index < a.size() - 1)
{
for (int i = 0; i <= a.at(index); i++)
{
if (i <= n)
{
res[index] = i;
dfs(a, n - i, index + 1, res);
}
}
}
else
{
if (n <= a.at(index))
{
res[index] = n;
for (int k = 0; k < res.size(); k++)
cout << res.at(k);
cout << endl;
}
}
return;
}
int main()
{
int K, N, i;
cin >> K >> N;
vector a;
for (int j = 0; j < K; j++)
{
cin >> i;
a.push_back(i);
}
int index = 0;
vector res;
for (int j = 0; j < K; j++)
{
res.push_back(0);
}
dfs(a, N, index, res);
return 0;
}
#include <iostream>
(720)#include <vector>
#include <string>
(765)#include <set>
using namespace std;
set<string> res;
vector<int> path;
//先选1个第一个,再选两个第2个与先选两个第二个再选一个第一个重复 ,将vector<string> res改为set<string> res后解决
void dfs(int n,vector<int> nums,string path){
if(n==0){ //只要次数选完了,就加入path
res.insert(path);
return;
}
for(int i=0;i<nums.size();i++){
if(nums[i]==0) continue;
path[i]+=1;
nums[i]-=1;
dfs(n-1,nums,path);
//回溯
nums[i]+=1;
path[i]-=1;
}
}
int main(void){
int M,N;
cin>>M>>N;
vector<int> num;
string path;
for(int i=0;i<M;i++) {
int t;
cin>>t;
num.push_back(t);
path+='0';
}
dfs(N,num,path);
for(auto i:res) cout<<i<<endl;
return 0;
} import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
public class Main {
private static List<Integer> path = new ArrayList<>();
public static void print(List<Integer> l, int k) {
StringBuilder sb = new StringBuilder();
l.forEach(u -> sb.append(u));
for (int i = l.size(); i < k; i++) {
sb.append(0);
}
System.out.println(sb.toString());
}
public static void run(int[] colors, int k, int n, int level) {
if (n == 0) {
print(path, k);
return;
}
if (level >= k) {
return;
}
for (int i = 0; i <= colors[level]; i++) {
path.add(i);
run(colors, k, n - i, level + 1);
path.remove(path.size() - 1);
}
}
private static List<List<Integer>> turn1 = new ArrayList<>();
public static void run_2(int[] colors, int k, int n, int level) {
if (k == 1) {
System.out.println(n);
return;
}
for (int i = 0; i <= colors[0]; i++) {
turn1.add(Arrays.asList(i));
}
List<Integer> temp;
for (int i = 1; i < k; i++) {
List<List<Integer>> lastTurn = turn1;
List<List<Integer>> nowTurn = new ArrayList<>();
for (int j = 0; j < lastTurn.size(); j++) {
for (int z = 0; z <= colors[i]; z++) {
temp = new ArrayList<>();
temp.addAll(lastTurn.get(j));
temp.add(z);
if (i == k-1) {
if (temp.stream().reduce(0, (u1, u2)->u1 + u2) == n) {
print(temp, k);
}
} else {
if (temp.stream().reduce(0, (u1, u2)->u1 + u2) <= n) {
nowTurn.add(temp);
}
}
}
}
turn1 = nowTurn;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int k = scanner.nextInt();
int n = scanner.nextInt();
int[] colors = new int[k];
for (int i = 0; i < k; i++) {
colors[i] = scanner.nextInt();
}
run_2(colors, k, n, 0);
}
}
}
public static void main(String [] args){
Scanner sc=new Scanner(System.in);
while(sc.hasNext()){
int k=sc.nextInt();
int n=sc.nextInt();
int [] nums=new int[k];
for(int i=0;i<k;i++){
nums[i]=sc.nextInt();
}
Stack<String> stack=new Stack<String>();
helper(nums,n,0,stack,"");
while(!stack.isEmpty()){
System.out.println(stack.pop());
}
}
}
private static void helper(int [] nums,int target,int index,Stack<String> stack,String string){
if(index==nums.length&&target==0){
stack.push(string);
return;
}
int nextTarget=0;
for(int i=Math.min(target,nums[index]);i>=0;i--){
nextTarget=target-i;
helper(nums,nextTarget,index+1,stack,string+"i");
}
}