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
原文地址:https://www.cnblogs.com/Phantom01/p/3637128.html