• 邮票面值设计 (动态规划+DFS)


    题意:https://ac.nowcoder.com/acm/problem/16813

    思路:

      深度搜索:每一层枚举一个面值,然后通过dp进行检查,并通过已知面值得到最多n张得到的最大表示数。

           其实,该搜索就是一个比较裸的,进行剪枝,枚举的面值还是存在范围的,上一次面值+1~n*sum(sum表示所有已知面值相加,其实这只是一个粗糙的剪枝,但是,对于我这种弱鸡莱来说还是香)

    更多,细节的解释还是在代码里。还有,有多余的输出,需要自己去删除。

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int n, k, res, ans[105], f[2005], curans[105];
    int solve(int dep, int sum){
        memset(f, 0x3f, sizeof(f));
        f[0] = 0;
        for (int i = 1; i <= dep; ++i){
            for (int j = curans[i]; j <= n*sum; ++j)            //完全背包,f[i]记录的是在已知的面值中选择最少数量
                f[j] = min(f[j], f[j - curans[i]] + 1);            //如果最少数量大于n时,说明i这个数字不能表示,但是
        }                                                        //i-1表示可表示的最大值。
        for (int i = 1; i <= n*sum; ++i){
            if (f[i] > n){
                return i - 1;
            }
        }
        return n*sum;
    }
    
    void dfs(int dep, int last, int maxn, int sum){
        if (dep > k){                                        //dep作为递归结束,maxn是一个估计上界(因为不能无限
            if (res < maxn){                                //枚举下去,但是面值肯定小于n*sum)
                res = maxn;                                    //而枚举的下界就是i+1
                for (int i = 1; i <= k; ++i){
                    ans[i] = curans[i];
                }
            }
            return;
        }
        for (int i = last + 1; i <= maxn + 1; ++i){
            curans[dep] = i;
            int x = solve(dep, sum + i);
            cout << "dep=" << dep<<endl;
            cout << "maxn=" << maxn << "   sum+i=" << sum + i << endl;
            cout << "x=" << x << endl;
            for (int i = 1; i <= dep; ++i)
                cout << "cur[" << i << "]="<<curans[i] << endl;
            cout << endl << endl;
            dfs(dep + 1, i, x, sum + i);
        }
    }
    
    int main(){
        cin >> n >> k;
        dfs(1, 0, 0, 0);
        for (int i = 1; i <= k; ++i)
            cout << ans[i] << " ";
        cout << endl << "MAX=" << res << endl;
    }
  • 相关阅读:
    excel查找定位操作(for lutai)
    sqlserver检查sql执行时间
    excel操作for(lutai)
    android studio 3.0+发布签名apk注意的情况
    二维码
    svn文件合并
    生成wsdl代理c#代码
    LOCK_TIMEOUT
    支持chrome30下载文件
    miniui处理多重子表级联,一次性提交多表数据的ui要点
  • 原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/10355545.html
Copyright © 2020-2023  润新知