zoukankan      html  css  js  c++  java
  • DAG上动态规划

    很多动态规划问题都可以转化为DAG上的最长路,最短路,或路径计数问题。

    硬币问题:

    有N中硬币,面值分别为v1,v2,v3,……vn,每种都无穷多,给定非负整数S,可以选用多少个硬币,使他们的总和恰好为S。输出硬币数目的最小值和最大值。

    解:每种面值看作一个点,表示:还需要凑足的面值。则开始状态为S,目标状态为0;若当前状态为i,当使用硬币j后,状态转为i-v[j].

    代码说明好了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <string>
     7 #include <vector>
     8 #include <set>
     9 #include <map>
    10 #include <queue>
    11 #include <stack>
    12 using namespace std;
    13 const int INF = 0x7fffffff;
    14 const double EXP = 1e-8;
    15 const int MS = 100005;
    16 int minv[MS], maxv[MS];
    17 int V[MS];
    18 int main()
    19 {
    20     fill(minv, minv + MS, INF);
    21     fill(maxv, maxv + MS, -INF);
    22     minv[0] = maxv[0] = 0;
    23     int N, S;
    24     cin >> N >> S;
    25     for (int i = 1; i <= N; i++)
    26         cin >> V[i];
    27 
    28     for (int i = 1; i <= S; i++)
    29         for (int j = 1; j <=N;j++)
    30             if (i >= V[j])
    31             {
    32                 minv[i] = min(minv[i], minv[i - V[j]] + 1);
    33                 maxv[i] = max(maxv[i], maxv[i - V[j]] + 1);
    34             }
    35     cout << minv[S] << " " << maxv[S] << endl;
    36     return 0;
    37 }

     输出字典序最小的方案:

     1 void print_ans(int *d, int s)
     2     {
     3         for (int i = 1; i <= n;i++)
     4             if (s >= v[i] && d[s] == d[s - v[i]] + 1)
     5             {
     6                 cout << i << " ";
     7                 print_ans(d, s - v[i]);
     8                 break;
     9             }
    10     }
    11     print_ans(minv, S);
    12     cout << endl;
    13     print_ans(maxv, S);

    另一种方法求字典序最小的方案。

    用min_coin[i]来记录状态为i时,最小的j,满足d[j]+1=d[i];

    code:

     1 for (int i = 1; i <= S; i++)
     2         for (int j = 1; j <= n; j++)
     3         {
     4             if (i > =v[j])
     5             {
     6                 if (minv[i] > minv[i - v[j]] + 1)  //如果j从大到小   则>=
     7                 {
     8                     minv[i] = minv[i - v[j]] + 1;
     9                     min_coin[i] = j;
    10                 }
    11                 if (maxv[i] < maxv[i - v[j]] + 1)  //如果j从大到小,则<=
    12                 {
    13                     maxv[i] = maxv[i - v[j]] + 1;
    14                     max_coin[i] = j;
    15                 }
    16             }
    17         }
    18     void print_ans(int *d, int S)
    19     {
    20         while (S)
    21         {
    22             cout << d[S] << " ";
    23             s -= v[d[s]];
    24         }
    25     }
    26     print_ans(min_coin, S);
    27     cout << endl;
    28     print_ans(max_coin, S);

    问题二:矩形嵌套。

    矩形的长宽为a,b;设一个矩形的长宽为a,b,另一个矩形长宽为c,d;当a<c&&b<d  或 b<c&&a<d时,两个矩形可以嵌套。

    现在给出N个矩形,嵌套组合为第一个嵌套在第二个,第二个可以嵌套在第三个,第三个可以嵌套在第四个,……。

    求数量多的嵌套组合的个数。

    解:DAG 法。每个矩形抽象为一个点,当矩形a可以嵌套在矩形b时,我们在a,b之间连一条边。那么问题转化为求DAG上的最长路径。

    设d[i]为从节点i出发的最长路径,则有d[i]=max(d[j]+1),   (i,j)是一条边。

     1 //记忆化搜索
     2     int d[MS];
     3     int dp(int i)
     4     {
     5         int &ans = d[i];
     6         if (ans > 0)
     7             return ans;
     8         ans = 1;
     9         for (int j = 1; j <= n; j++)
    10             if (G[i][j])
    11                 ans = max(ans, dp(j)+ 1);
    12         return ans;
    13     }

     输出字典序最小的方案:

     1 void print_ans(int i)   //  d[i]==max  &&  i is smallest
     2     {
     3         cout << i << " ";
     4         for (int j = 1; j <= n; j++)
     5         {
     6             if (G[i][j] && d[i] == d[j] + 1)
     7             {
     8                 print_ans(j);
     9                 break;
    10             }
    11         }
    12     }
  • 相关阅读:
    springmvc 处理静态资源
    springmvc jsp 获取 上下文
    springmvc 如何设置首页
    servlet-mapping url-pattern / 和 /*区别
    nginx支持php
    openresty 变量
    git tag用法
    python 导入模块,__init__.py 的作用
    python 转码问题
    python装饰器
  • 原文地址:https://www.cnblogs.com/767355675hutaishi/p/4268643.html
Copyright © 2011-2022 走看看