• L3-001. 凑零钱(dfs或者01背包)


    L3-001. 凑零钱

    时间限制
    200 ms
    内存限制
    65536 kB
    代码长度限制
    8000 B
    判题程序
    Standard
    作者
    陈越

    韩梅梅喜欢满宇宙到处逛街。现在她逛到了一家火星店里,发现这家店有个特别的规矩:你可以用任何星球的硬币付钱,但是绝不找零,当然也不能欠债。韩梅梅手边有104枚来自各个星球的硬币,需要请你帮她盘算一下,是否可能精确凑出要付的款额。

    输入格式:

    输入第一行给出两个正整数:N(<=104)是硬币的总个数,M(<=102)是韩梅梅要付的款额。第二行给出N枚硬币的正整数面值。数字间以空格分隔。

    输出格式:

    在一行中输出硬币的面值 V1 <= V2 <= ... <= Vk,满足条件 V1 + V2 + ... + Vk = M。数字间以1个空格分隔,行首尾不得有多余空格。若解不唯一,则输出最小序列。若无解,则输出“No Solution”。

    注:我们说序列{A[1], A[2], ...}比{B[1], B[2], ...}“小”,是指存在 k >= 1 使得 A[i]=B[i] 对所有 i < k 成立,并且 A[k] < B[k]。

    输入样例1:
    8 9
    5 9 8 7 2 3 4 1
    
    输出样例1:
    1 3 5
    
    输入样例2:
    4 8
    7 2 4 3
    
    输出样例2:
    No Solution

    #include <bits/stdc++.h>  
    using namespace std;  
    #define maxn 11000  
    int vis[maxn];  
    int s[maxn];  
    int tmp[maxn];  
    int n, m;  
    int cnt;  
    int flag;  
    int all;  
    void dfs(int index,int sum, int cnt,int tol)//tol 为剩余的钱数  
    {  
        if(flag || sum > m || tol < m - sum)  
            return;  
        if(sum == m)  
        {  
            for(int i = 0; i < cnt - 1; i++)  
                printf("%d ",tmp[i]);  
            printf("%d
    ",tmp[cnt - 1]);  
            flag = 1;  
            return;  
        }  
        for(int i = index + 1; i < n; i++)  
        {  
            if(!vis[i] && s[i] <= m - sum)  
            {  
                vis[i] = 1;  
                tmp[cnt] = s[i];  
                dfs(i,sum + s[i], cnt+1, tol - s[i]);  
                if(flag) return;  
                vis[i] = 0;  
            }  
        }  
    }  
    int main()  
    {  
      
        scanf("%d%d", &n, &m);  
        all = 0;  
        for(int i = 0; i < n; i++)  
        {  
            scanf("%d", &s[i]);  
            all += s[i];  
        }  
        sort(s, s + n);  
        cnt = 0;  
        dfs(-1,0, cnt,all);  
        if(!flag)  
            printf("No Solution
    ");  
    } 

    01

    本来背包判断是否存在,然后dfs的 但是只有28分   然后学了下记录路径

    b[sum]=a[i] 就是代表 sum的钱=a[i]+b[ sum-a[i] ] 这样递归下去 直接sum=0 这样就得到路径了

    #include <bits/stdc++.h>
    using namespace std;
     
    int dp[10005];
    int b[10005];
    int a[10005];
     
    void dfs(int t)
    {
        if(t==b[t])
        {
            printf("%d",b[t]);
            return ;
        }
        dfs(t-b[t]);
        printf(" %d",b[t]);
    }
     
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
     
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1);
        for(int i=1; i<=n; i++)
        {
            for(int j=m; j>=a[i]; j--)
            {
                if(dp[j-a[i]] || j==a[i])//是否到达过  || 直接到达
                {
                    if(dp[j]<=dp[j-a[i]]+1)//dp[j] 表示j是由dp[j]个数组成 又因为数越多 组成的序列越小 数相同 用=号去更新 
                    {
                        dp[j] = dp[j-a[i]]+1;
                        b[j] = a[i];  //钱是j的时候 是由 (j-a[i])的时候+a[i]过来的
                    }
                }
            }
        }
     
        if(!b[m])
            puts("No Solution");
        else dfs(m),puts("");
        return 0;
    }

    我28分的dfs

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<map>
    #include<set>
    using namespace std;
    int a[10005];
    bool v[10005];
    int c[10005];
    int k=1;
        int n,m;
            bool f=0;
    
    void display(int s)
    {
        for(int i=1;i<=n;i++)
        {
                    if(c[i]==0) break;
            if(i!=1) cout<<" ";
    
            cout<<c[i];
        }
    }
    
    void dfs(int sum,int s)
    {
        if(s>n||sum>m) return;
        if(sum==m)
        {
            display(s);
            f=1;
            return;
        }
    
        for(int i=1;i<=k-1;i++)
        {
            if(v[i]) continue;
            else 
            {
                v[i]=1;
                c[s]=a[i];
                dfs(sum+a[i],s+1);
                c[s]=0;
                if(f) return;
                v[i]=0;
            }
        }
    }
    
    
    
    int main()
    {
    
    
        cin>>n>>m;
        memset(v,0,sizeof v);
        for(int i=1;i<=n;i++)
        {
            int x;
            cin>>x;
            if(x>m) continue;
            a[k++]=x;
        }
            sort(a+1,a+k);
            dfs(0,1);
            if(!f) cout<<"No Solution";
    }
    View Code
  • 相关阅读:
    [C#] override和overload的区别
    [ASP.Net] 20141228_Dapper文章搜集
    JSP
    Ajax使用简介
    编写JAVA脚本的JSP页面
    JAVA web开发模式
    JSP基础
    过滤器
    监听会话范围内事件
    http解析
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13271074.html
Copyright © 2020-2023  润新知