zoukankan      html  css  js  c++  java
  • WHU 1538 Stones II 动态规划

    赛后写的,动态规划,学长和题解,提供了两种状态设计的思路,都写了下……结果在写第二种的时候,不小心把下标的起点写错了,导致WA了无数发…… 无奈啊……每次都是这种错误……

    题意:

      大概就是有n块石头,每块石头有两个值ai和bi,其中ai是价值。要求你从中选任意块,获得的价值最大。

      但是,每当你选了一块石头,此时没有被你选到得石头的价值都会剪掉这块石头的bi。

    思路:

      首先,可以证明,如果被选,bi小的肯定被先选。因为,如果某两块石头,bi大的先选了;那么交换这两块石头的选取顺序,可以得到更大的价值。

      因此,我们可以把所有的石头按照bi排序。这样子来贪心。

    接下来是动态规划:

      状态1:dp[i][j]表示 选取到第i个石头,选到的bi总和是j。 这样的话,在选取下一个石头的时候,那个石头的 ai - j 才是它能获得的价值。

      这种解法下的代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int MAXN = 1030;
     8 
     9 struct node {
    10     int a, b;
    11     bool operator < (const node & x) const {
    12         return b < x.b;
    13     }
    14 }a[MAXN];
    15 
    16 int n;
    17 int dp[MAXN]; ///dp[i][j]
    18 
    19 int main() {
    20     #ifdef Phantom01
    21 //        freopen("WHU1538.txt", "r", stdin);
    22     #endif // Phantom01
    23 
    24     while (scanf("%d", &n)!=EOF) {
    25         if (0==n) break;
    26 
    27         for (int i = 0; i < n; i++)
    28             scanf("%d%d", &a[i].a, &a[i].b);
    29         sort(a, a+n);
    30         memset(dp, 0, sizeof(dp));
    31         for (int i = 0; i < n; i++) {
    32             for (int j = MAXN-1; j >= 0; j--) {
    33                 if (a[i].b+j <= 1005)
    34                     dp[a[i].b+j] = max(dp[a[i].b+j], dp[j]+a[i].a-j);
    35                 else
    36                     dp[1006] = max(dp[1006], dp[j]+a[i].a-j);
    37             }
    38         }
    39         int ans = 0;
    40         for (int i = 0; i < MAXN; i++)
    41             ans = max(ans, dp[i]);
    42         printf("%d
    ", ans);
    43     }
    44 
    45     return 0;
    46 }
    Solution 1

      状态2:dp[i][j]表示 选到第i个石头,后面还要选j块石头。 这样子的话,这块石头在整个过程中能够提供的价值是 ai - J * bi

      代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int MAXN = 1050;
     8 
     9 struct node {
    10     int a, b;
    11     bool operator < (const node &x) const {
    12         return b < x.b;
    13     }
    14 }a[MAXN];
    15 
    16 int n;
    17 int dp[MAXN];
    18 
    19 int main() {
    20     #ifdef Phantom01
    21         freopen("1538_1.in", "r", stdin);
    22     #endif // Phantom01
    23 
    24     while (scanf("%d", &n)!=EOF) {
    25         if (0==n) break;
    26 
    27         memset(dp, 0, sizeof(dp));
    28         for (int i = 0; i < n; i++)
    29             scanf("%d%d", &a[i].a, &a[i].b);
    30         sort(a, a+n);
    31         for (int i = 0; i < n; i++) {
    32             for (int j = 0; j <= n; j++) {
    33                 dp[j] = max(dp[j], dp[j+1]+a[i].a-j*a[i].b);
    34             }
    35         }
    36         printf("%d
    ", dp[0]);
    37     }
    38 
    39     return 0;
    40 }
    Solution 2
  • 相关阅读:
    SGU180:Inversions(树状数组)
    Android布局中match_parent和fill_parent的差别
    上拉电阻和下拉电阻
    iOS应用性能调优的25个建议和技巧
    《拼音字母》 蓝桥杯复试试题
    构建轻量级的Table View注意事项[UIKit]
    Spark学习(一) 基本操作
    水滴状的自己定义视图,让您摆脱单调的Dialog
    【Scala】使用Option、Some、None,避免使用null
    基于tornado实现web camera
  • 原文地址:https://www.cnblogs.com/Phantom01/p/3637128.html
Copyright © 2011-2022 走看看