首页 > 试题广场 >

薯券使用问题

[编程题]薯券使用问题
  • 热度指数:2976 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
某小红薯在小红书的活动中抽奖中了一定价值的薯券,这些薯券可以用来购买一批商品,求有多少种购买组合。其中一件商品可以买多件。
输 入:薯券金额、商品分别价格
输出 :组合数

输入描述:
输入薯券金额、商品分别价格
例如:10 [2,3,5]
10与[2,3,5]中间有空格


输出描述:
输出4,则结果集可以为:2,2,2,2,2;5,5;2,3,5;2,2,3,3共有4种组合 
示例1

输入

10 [2,3,5]

输出

4
 例如10 [2,3,5],先10-0 * 5 = 10,10-1* 5 =5,10-2* 5 =10。然后依次对10 [2,3]; 5[2,3]; 0[2,3]进行递归 。采用全局变量 记录,空间复杂度O(1)。通过90%,最后告诉我浮点错误,懵了,全代码只进行一次对商品价格的取余运算,这都浮点错误。
#include <iostream> #include <vector> #include <stdlib.h> #include <math.h> #include <算法>使用名称空间std;整数l = 0; vector <int> p;整数int ans = 0 ; int dg(int loc,int n){// loc记录当前数组元素位置,n记录当前余额如果(n == 0){ans ++;返回0;}如果(loc == 0){if(n%p [0] == 0)ans ++;//到最小商品,可整除则ans ++返回0;}如果(n <p [0])返回0; int temp = n;而(temp> = 0){dg(loc-1,temp);//进行下一轮递归temp- = p [loc];//最初的商品价格}返回0;} int main(){cin >> num;图表而(cin >> t){如果(t ==']')中断; if(t-'0'<= 9 && t-'0'> = 0){int tt = t-'0';p.push_back(tt);l = p.size();sort(p.begin(),p.end());dg(l-1,num);cout << ans << endl;返回0;}

编辑于 2020-06-16 01:52:44 回复(0)

与力扣 面试题 08.11. 硬币 这题一样

import java.util.*;

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        String s = in.next();
        String[] tmp = s.substring(1, s.length() - 1).split(",");
        int[] arr = new int[n + 1];
        int[] p = new int[tmp.length];
        for(int i = 0; i < tmp.length; i++) {
            p[i] = Integer.parseInt(tmp[i]);
        }

        arr[0] = 1;

        for(int a : p) {
            for(int i = a; i < arr.length; i++) {
                arr[i] = (arr[i] + arr[i - a]);
            }
        }

        System.out.println(arr[n]);
    }

}
编辑于 2020-06-20 16:13:26 回复(1)

解题思路: 动态规划/背包问题
定义数组dp[i][j]表示金额为j的情况下,对于前i种商品,最多可以有多少种组合。
初始状态:
dp[...][0] = 1表示在金额为0的情况下,无论有几种商品,只能有一种组合,那就是什么都不取这一种。
状态转移:
如果不选择当前第i个商品,组合数 dp[i-1][j]
如果选择当前第i个商品,组合数 dp[i][j-v[i-1]]

得出状态转移方程:
dp[i][j] = dp[i-1][j] + dp[i][j-v[i]] (v[i]表示商品的最大金额)

解释: dp[2][10] = dp[1][10] + dp[2][10-5] = 2 + 2 = 4

0 1 2 3 4 5 6 7 8 9 10
2 1 0 1 0 1 0 1 0 1 0 1
2,3 1 0 1 1 1 1 2 1 2 1 2
2,3,5 1 0 1 1 1 2 2 2 3 3 4
//代码如下
import java.util.*;
public class Main {
    public int solution(int a[],int v){
        int dp[][] = new int[a.length][v+1];
        for (int i = 0; i < dp.length; i++) {
            dp[i][0]=1;
            for (int j = 1; j < dp[i].length; j++) {
                if(i==0){
                    if(j<a[i]){
                        dp[i][j]=0;
                    }else {
                        dp[i][j]=dp[i][j-a[i]];
                    }
                }else {
                    if(j<a[i]){
                        dp[i][j]=dp[i-1][j];
                    }else {
                        dp[i][j]=dp[i-1][j]+dp[i][j-a[i]];
                    }
                }
            }
        }
        return dp[dp.length-1][v];
    }
    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        String[] s1 = s.split(" ");
        int v = Integer.parseInt(s1[0]);
        String[] s2 = s1[1].substring(1,s1[1].length()-1).split(",");
        int[] a = new int[s2.length];
        for (int i = 0; i < a.length; i++) {
            a[i] = Integer.parseInt(s2[i]);
        }
        System.out.println(new Main().solution(a, v));
    }
}
编辑于 2020-10-04 00:24:34 回复(0)
刚开始格式输入错误都有10%的正确率。。。
其实就是动态规划。

dp[j]为当前价格j时的方案数,dp[0]就是价格为0时有一种方案(不给就好了),然后从每张券开始遍历就好了。
#include<iostream>
#include<vector>
using namespace std;
int main(){
	int n, i= 0;
	cin>>n;
	int dp[10000] = {0};
	dp[0] = 1;
	vector<int> data;
	string Stringdata;
	cin>>Stringdata;
	while (i < Stringdata.length())
	    {
	        if (Stringdata[i] != ' ' && Stringdata[i] != '[' && Stringdata[i] != ',' && Stringdata[i] != ']')
	        {
	            int sum = 0;
	            while (Stringdata[i] != ',' && Stringdata[i] != ']')
	            {
	                sum *= 10;
	                sum += Stringdata[i] - '0';
	                i++;
	            }
	            data.push_back(sum);
	        }
	        else
	        {
	            i++;
	        }
	    }
	for(int c = 0; c < data.size(); c++){
		for(int j = data[c]; j <= n; j++){
			dp[j] += dp[j-data[c]];
		}
	}
	cout<<dp[n]<<endl;
}


发表于 2020-07-02 20:49:17 回复(1)
动态规划:
    f(i,j)表示选择前i种商品构成消费券价值为j的方案数量,price_i表示第i种商品的价格。
状态转移:
        f(i,j) = f(i-1,j)+    f(i-1,j-1*price_i)...+f(i-1,j-k*price_i),   k=(j/price_i)
因为
        f(i,j-price_i) =    f(i-1,j-price_i)+.....+f(i-1,j-k*price_i)
故状态转移方程:
        f(i,j) = f(i-1,j)+f(i,j-price_i)
str1 = input()
arr = str1.split()
# 购物券的价格
money = int(arr[0])  
# 获取商品的价格列表
price = [int(i) for i in arr[1] if i.isdigit()]
# 商品列表长度
n = len(price)
# 记录状态值
dp = [[0 for i in range(money+1)]for j in range(n+1)]
for i in range(1,n+1):
    dp[i][0] = 1  # 给定初始值
for i in range(1,n+1):
    for j in range(1,money+1):
        dp[i][j] = dp[i-1][j]
        if j>=price[i-1]:
            dp[i][j]+=dp[i][j-price[i-1]]
print(dp[-1][-1])
但是只能通过90%的案例,最后一个结果案例的结果比较大,应该要对其取相应的余数,但是题目没有告诉。

发表于 2020-06-09 17:00:49 回复(1)
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            int total = scanner.nextInt();
            String ret = scanner.nextLine();
            ret = ret.substring(2, ret.length() - 1);//因为读入了空格
            String[] elem = ret.split(",");

            //使用dp[i][j]  定义数组dp[i][j]表示金额为j的情况下,对于前i种商品,最多可以有多少种组合。
            //1、如果不取j商品  那么dp[i][j]=dp[i-1][j]
            //2、如果取j商品  那么dp[i][j]= dp[i]  [j-Value[i-1]]  (Value[i-1]对应此商品价格) 完全背包问题 因此是 dp[i]  [j-Value[i-1]]

            int[][] dp = new int[elem.length + 1][total+1];
            //对于 价格为0时 不买任何商品  这种组合是1
            for (int i = 0; i <= elem.length; i++) {
                dp[i][0] = 1;
            }
            for (int i = 1; i <= elem.length; i++) {//商品个数
                for (int j = 1; j <= total; j++) {//花费金额

                    if (j >= Integer.parseInt(elem[i - 1]))
                        dp[i][j] = dp[i - 1][j] + dp[i][j - Integer.parseInt(elem[i - 1])];
                    else
                        dp[i][j] = dp[i - 1][j];

                }
            }

            System.out.println(dp[elem.length][total]);
        }

发表于 2023-06-18 00:40:13 回复(0)
package main
 
import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)
 
func main() {
    inputReader := bufio.NewReader(os.Stdin)
    line, _ := inputReader.ReadString('\n')
    line = strings.Replace(line, "\n", "", -1)
    lines := strings.Split(line, " ")
    n, _ := strconv.Atoi(lines[0])
    lines[1] = lines[1][1:]
    lines[1] = lines[1][:len(lines[1])-1]
    s := strings.Split(lines[1], ",")
    nums := []int{}
    for _, c := range s {
        temp, _ := strconv.Atoi(c)
        nums = append(nums, temp)
    }
    dp := make([]int, n+1)
    dp[0] = 1
 
    for _, j := range nums {
        for i := j; i <= n; i++ {
            dp[i] += dp[i-j]
        }
    }
 
 
    fmt.Print(dp[n])
}

发表于 2022-08-28 22:09:32 回复(0)
这个输入格式真恶心
发表于 2022-08-27 17:01:02 回复(0)
import java.lang.*;
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        List<Integer> prices = new ArrayList<>();
        
        String s = scanner.nextLine();
        String[] listStr = s.substring(2,s.length()-1).split(",");
        for(int i = 0;i<listStr.length;i++){
            prices.add(Integer.parseInt(listStr[i]));
        }
        
        int[] dp = new int[num+1];
        dp[0] = 1;
        for(int i = 0;i<prices.size();i++){
            for(int j = prices.get(i);j<=num;j++){
                dp[j]+=dp[j-prices.get(i)];
            }
        }
        System.out.println(dp[num]);
    }
}
发表于 2022-08-05 22:42:14 回复(0)
背包问题,外边遍历物品,里面从头往后遍历背包容量,可以是物品添加多次
import java.util.*;
public class Main{
    
    public static void main(String[] args){
        
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        String str = sc.next();
        str = str.substring( 1 , str.length() - 1);
        String[] strs = str.split(",");
        int length = strs.length;
        int[] array = new int[length];
        int[] dp = new int[N+1];
        dp[0]=1;
        for(int i = 0 ;i < length ; i++ ){
            array[i] = Integer.parseInt(strs[i]);
        }
        
        for(int i = 0 ; i <length ; i++ ){
            for(int j = array[i] ; j <= N ; j++ ){
                dp[j] = dp[j] + dp[ j - array[i] ];
            }
        }
        System.out.println(dp[N]);
    }
}



发表于 2022-03-01 22:25:20 回复(0)
str1 = '10 [2,3,5]'
arr = str1.split()
# 购物券的价格
m = int(arr[0])
# 获取商品的价格列表 235
price = [int(i) for i in arr[1] if i.isdigit()]
# 商品列表长度
n = len(price)
rslt = []#储存答案
cou = 0
tmp = []
def get_buys(money, value):#每轮买商品都会触发
    global  ind
    global tmp#全局变量 用来储存已经买的商品
    global cou#全局变量,每次正好花光十元钱,+1
    global price
    if (value and money - value >= 2):#判断,要买的商品价格不为空 且当前的钱减去要买的价格>=2 PS:减完之后小于2,就什么都买不了了
            last=0
            # tmp = tmp[0:-1:]
            tmp.append(value)#储存当前买的
            money -= value#钱减少
            return get_buys(money, 0)#跳进下一个购买动作
    if value and money - value < 2:#如果买完之后钱不够2
        if money-value==0:#等于零
            tmp.append(value)#储存当前买的
            rslt.append(tmp);#将这个方案存入答案中
            cou+=1#解决问题次数+1
            try: ind = tmp.index(5);
            except: ind=None;
            if ind:
                tmp = tmp[0:ind-1:];#如果曾经买过5,还要退掉五之前买的那一个以及之后买的所有东西
            else:
                tmp=tmp[0:-1:]#退掉刚刚买的
            return  1
        else:
            # tmp.append(value)
            # tmp = tmp[0:-1:];
            if value == 5: tmp = tmp[0:-1:];  # 退掉上次选择的商品
    if (not value):
           return [ get_buys(money, p) for p in price ]
get_buys(m, 0)
s=set()
for r in rslt:
    r.sort()
all =list(str(r) for r in rslt)
for a in all:
    s.add(a)
print (len(s))


发表于 2022-01-28 02:09:49 回复(0)
用了回溯,过了70%,后面说内存超了,唉
#include <iostream>
#include <vector>
#include <string>
using namespace std;
 
class Solution{
public:
    void fun(){
        string price;
        int money;
        vector<int> vec;
        cin >> money >> price;
        for(int i = 1; i < price.length() - 1; i += 2){
            int val = price[i] - '0';
            vec.emplace_back(val);
        }
        dfs(vec, 0, money, 0);
        cout << all << endl;
        return;
    }
    void dfs(vector<int> &nums, int cursum, int money, int begin){
        if(cursum == money){
            ++all;
        }
        for(int i = begin; i < nums.size(); ++i){
            if(cursum + nums[i] <= money){
                cursum += nums[i];
                dfs(nums, cursum, money, i);
                cursum = cursum - nums[i];
            }
        }
    }
private:
    int all = 0;
};
int main(){
    Solution a;
    a.fun();
    return 0;
}


发表于 2020-11-29 11:28:23 回复(0)
完全背包。
#include<bits/stdc++.h>
using namespace std;

int main()
{
    int sum;
    string s;
    while(cin>>sum>>s)
    {
        s.pop_back();
        int st=1;
        vector<int> v;
        while(st<s.size())
        {
            int pos=s.find(',',st);
            if(pos==string::npos)
            {
                v.push_back(stoi(s.substr(st)));
                break;
            }
            else{
                v.push_back(stoi(s.substr(st,pos-st)));
                st=pos+1;
            }
        }
        int dp[sum+1];
        memset(dp,0,sizeof dp);
        dp[0]=1;
        sort(v.begin(),v.end(),less<int>());
        //for(auto &i:v)    cout<<i<<" ";
        for(int i=0;i<v.size();i++)
        {
            for(int j=v[i];j<=sum;j++)
            {
                dp[j]=dp[j]+dp[j-v[i]];
            }
        }
        cout<<dp[sum]<<endl;
    }
    return 0;
}



发表于 2020-09-05 16:19:33 回复(0)
#include<iostream>        //动态规划
#include<string>
#include<vector>
using namespace  std;
int main()
{
    string s;
    int n;
    cin>>n;
    cin>>s;
    vector<int> v;
    int count=0;
    string t;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]>='0' && s[i]<='9')
         t+=s[i];
        else 
        {
            if(t.size()>0)
            {
                v.push_back(stoi(t,0,10));
                count++;
                t="";
            }
        }
    }
    vector<int> dp(n+1);
    dp[0]=1;
        for(int j=0;j<count;j++)                           
        {
           for(int i=1;i<=n;i++)
         {
               if(i>=v[j])
              dp[i]=dp[i]+dp[i-v[j]];  
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}
编辑于 2020-08-28 22:48:53 回复(0)
class Solution:
    def Totalnumberofcombinations(self,num,lis):
        lis=sorted(lis)
        return self.back(num,lis)
    def back(self,num,lis):
        count=0  #这个初始化非常重要
        i=0
        while i<len(lis):
            if num-lis[i]>0:
                count+=self.back(num-lis[i],lis[i:])
                i+=1
            elif num-lis[i]==0:
                count+=1
                return count
            else:
                return count
        return count
ss=Solution()
str1 = input()
arr = str1.split()
num= int(arr[0])
srr=arr[1][1:len(arr[1])-1]
lis= [ int(i) for i in srr.split(",")]
res=ss.Totalnumberofcombinations(num,lis)
print(res)
运用的回溯方法,不过找不出来为什么只通过了50%,有没有Python通过的代码啊,求解答
发表于 2020-07-23 15:34:53 回复(0)
data = input()
n, a = data.split()
n = eval(n)
a = eval(a)
di = {}
 
 
def go(ind, left):
    global ans
    if left < 0:
        return 0
    k = (ind, left)
    if k in di:
        return di[k]
    if ind == len(a):
        if left == 0:
            di[k] = 1
        else:
            di[k] = 0
        return di[k]
    s = 0
    for c in range(left // a[ind] + 1):
        s += go(ind + 1, left - c * a[ind])
    di[k] = s
    return s
 
 
ans = go(0, n)
ans &= (1 << 32) - 1
print(ans)


这题答案有问题,最终结果会int溢出!!!!答案错了,结果还要我自己手动取int
发表于 2020-06-22 12:43:01 回复(1)
import java.util.Arrays;
import java.util.Scanner;

public class ShuJuan {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int sum = scanner.nextInt();
        String next = scanner.next();
        int length = next.length();
        String subString = next.substring(1,length-1);
        String[] split = subString.split(",");
        int[] prices = new int[split.length];
        for(int i = 0;i < split.length;i++){
            prices[i] = Integer.parseInt(split[i]);
        }
        Arrays.sort(prices);
        System.out.println(dfs(sum,prices,0,0));
    }
    private static int dfs(int totalmoney,int[] zonglei,int start,int num){
        if(totalmoney<0){
            return 0;
        }
        for(int i=start;i<zonglei.length;i++){
            if(totalmoney-zonglei[i]<=0){
                if(totalmoney-zonglei[i]==0) {
                    num+=1;
                    return num;
                }
                break;
            }
            num=dfs(totalmoney-zonglei[i],zonglei,i,num);
        }
        return num;
    }
}

只能通过70%的dfs分享下
发表于 2020-06-17 21:09:19 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<vector<int> >result;
//这里location的作用是为了防止出现重复的数组
void fun2(int sum,vector<int>&data,vector<int>&temp,int location)
{
	if (sum == 0)
	{
		result.push_back(temp);
		return;
	}
	else if(sum<0)
	{
		return;
	}
	else {
		for (int i = location; i < data.size();i++ )
		{
			sum -= data[i];
			temp.push_back(data[i]);
			fun2(sum, data, temp,i);
			sum += data[i];
			temp.pop_back();
		}
	}
}
void fun1(int sum, vector<int>& data)
{

	vector<int> temp;
	for (int i = 0; i < data.size(); i++)
	{
		temp.push_back(data[i]);
		sum -= data[i];
		fun2(sum, data, temp,i);
		sum += data[i];
		temp.pop_back();
	}
	
}
int main() {
	string Stringdata;
	int n;
	//cout << "请输入总价格:" << endl;
	cin >> n;
	//cout << "请输入每个优惠券的值:类似于[2,3,5]:" << endl;
	cin >> Stringdata;
	int i = 0;
	vector<int>data;
	while (Stringdata[i] == ' ')
		i++;
	while (i < Stringdata.length())
	{
		if (Stringdata[i] != ' ' && Stringdata[i] != '[' && Stringdata[i] != ',' && Stringdata[i] != ']')
		{
			int sum = 0;
			while (Stringdata[i] != ',' && Stringdata[i] != ']')
			{
				sum *= 10;
				sum += Stringdata[i] - '0';
				i++;
			}
			data.push_back(sum);
		}
		else
		{
			i++;
		}
	}
	sort(data.begin(),data.end());
	cout << endl;
	fun1(n, data);
	cout <<"size:"<< result.size() << endl;
	for (int i = 0; i < result.size(); i++)
	{
		for (int j = 0; j < result[i].size(); j++)
		{
			cout << result[i][j];
		}
		cout << endl;
	}
}

发表于 2020-06-11 17:24:07 回复(1)
#include <cmath>
#include <climits>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <stack>
#include <numeric>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
using namespace std;

class Solution{
    public:
    long long int solve(int sum, vector<int> prices){
        int pricesSize = prices.size();
        vector<vector<long long int>> dp(pricesSize+1, vector<long long int>(sum+1, 0));
        dp[0][0] = 1;
        for(int i = 1; i<=pricesSize; i++){
            for(int j=0; j<=sum; j++){
                for(int k=0; j + k <= sum; k+=prices[i-1]){
                    if(dp[i-1][j]>0){
                        dp[i][j+k] += dp[i-1][j];
                    }
                }
            }
        }
        return dp[pricesSize][sum];
    }
};
int main(){
    Solution a;
    int count;
    string str;
    cin >> count;
    cin >> str;
    if(str.find("[")!= string::npos){
        str=str.replace(str.find("["),1,"");
    }
    if(str.find("]")!= string::npos){
        str=str.replace(str.find("]"),1,"");
    }
    istringstream iss(str);
    vector<int> prices;
    string tmp;
    while(getline(iss, tmp, ',')){
        prices.push_back(atoi(tmp.c_str()));
    }
    cout << a.solve(count, prices) % 4294967296 << endl;
}
// 最后的徐亚哦对 4294967296(2^32) 取余
发表于 2020-06-11 13:17:55 回复(0)
class Solution {
private: 
        vector<vector<int> >res;
        vector<int>path;
        vector<int>candidates;
public:
    void dfs(int cnt,int target)
    {
        if(target==0)
        {
            res.push_back(path);
            return;
        }
        for(int i=cnt;i<candidates.size() && target-candidates[i]>=0;i++)
        {
            path.push_back(candidates[i]);
            dfs(i,target-candidates[i]);
            path.pop_back();
        }
    }
     vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        sort(candidates.begin(),candidates.end());
          this->candidates = candidates;
        dfs(0,target);
        return res;
    }
};

发表于 2020-06-10 16:59:59 回复(0)