• NOIP 2014飞扬的小鸟(DP优化)


    题目链接  飞扬的小鸟

    考场的70分暴力(实际只有50分因为数组开小了……)

    考场代码(数组大小已修改)

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <functional>
     6 
     7 using namespace std;
     8 
     9 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
    10 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
    11 #define LL        long long
    12 #define fi        first
    13 #define se        second
    14 
    15 
    16 const int INF = 1    <<    30;
    17 const int N = 10000    +    10;
    18 const int M = 1000    +    10;
    19 
    20 int dp[M][N], x[N], y[N], u[N], d[N];
    21 int n, m, q, ans, xn, ln, rn, _max, pos;
    22 bool c[N];
    23 
    24 int main(){
    25 
    26     scanf("%d %d %d ", &n, &m, &q);
    27     rep(i, 0, n - 1) scanf("%d %d ", x + i, y + i);
    28     rep(i, 0, n) u[i] = m, d[i] = 1;
    29     memset(c, false, sizeof c);
    30     rep(i, 1, q){ 
    31         scanf("%d %d %d ", &xn, &ln, &rn); 
    32         c[xn] = true;
    33         u[xn] = rn - 1;  
    34         d[xn] = ln + 1;
    35     }
    36     //rep(i, 0, n) printf("%d %d
    ", d[i], u[i]);
    37     memset(dp, 0xff70, sizeof dp);_max = dp[1][1];
    38     rep(i, 0, m) dp[0][i] = 0;
    39     rep(i, 0, n - 1){
    40         rep(j, d[i], u[i]){
    41             if (dp[i][j] >= _max) continue;
    42             int k = j - y[i];
    43             if (k >= 0 && k <= m) dp[i + 1][k] = min(dp[i + 1][k], dp[i][j]);
    44             k = j;int num = 0;
    45             while (true){
    46                 k += x[i]; ++num;
    47                 if (k > m) k = m;
    48                 if (k >= 0 && k <= m) dp[i + 1][k] = min(dp[i + 1][k], dp[i][j] + num);
    49                 if (k == m) break;
    50             }
    51         }
    52     }
    53     
    54     ans = _max;
    55     rep(i, 1, m) ans = min(ans, dp[n][i]);
    56     if (ans < _max){
    57         printf("%d
    %d
    ", 1, ans);return 0;
    58     }
    59     
    60     bool flag = false;
    61     ans = 0;
    62     dec(i, n, 0) {rep(j, 0, m)  if (dp[i][j] < _max) { pos = i - 1;flag = true; break;} if (flag) break;}
    63     dec(i, pos, 0) if (c[i]) ++ans;
    64     printf("%d
    %d
    ", 0, ans);
    65     
    66     
    67     
    68     return 0;
    69 }

    然后回过来想正解。

    其实我们把很多时间都浪费在这里了:

    1     while (true){
    2         k += x[i]; ++num;
    3         if (k > m) k = m;
    4         if (k >= 0 && k <= m) dp[i + 1][k] = min(dp[i + 1][k], dp[i][j] + num);
    5         if (k == m) break;
    6     }

    其实这一步可以转过来直接利用完全背包的性质优化一下。转移只要O(1)就可以了。

    这道题细节还是很多的,比较容易写挂。

    正解:

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
     6 #define dec(i, a, b)    for (int i(a); i >= (b); --i)
     7 
     8 const int INF = 1    <<    29;
     9 const int N = 10000    +    10;
    10 const int M = 1000    +    10;
    11 
    12 int dp[N][M], x[N], y[N], u[N], d[N];
    13 int n, m, q, ans, xn, ln, rn, _max, pos;
    14 bool c[N];
    15 
    16 int main(){
    17 
    18     scanf("%d %d %d ", &n, &m, &q);
    19     u[n] = m + 1; d[n] = 0;
    20     rep(i, 0, n - 1) scanf("%d %d ", x + i, y + i), u[i] = m + 1, d[i] = 0;
    21 
    22 
    23     rep(i, 1, q){ 
    24         scanf("%d %d %d ", &xn, &ln, &rn); 
    25         u[xn] = rn;  
    26         d[xn] = ln;
    27     }
    28 
    29     rep(i, 0, n + 2) rep(j, 0, m + 2) dp[i][j] = INF;
    30 
    31     rep(i, 1, m) dp[0][i] = 0;
    32     rep(i, 1, n){
    33         rep(j, x[i - 1], m){
    34             dp[i][j] = min(dp[i][j], dp[i - 1][j - x[i - 1]] + 1);
    35             dp[i][j] = min(dp[i][j], dp[i][j - x[i - 1]] + 1);
    36         }
    37 
    38         rep(j, m - x[i - 1], m){
    39             dp[i][m] = min(dp[i][m], dp[i - 1][j] + 1);
    40             dp[i][m] = min(dp[i][m], dp[i][j] + 1);
    41         }
    42 
    43         rep(j, d[i] + 1, u[i] - 1){
    44             if (j + y[i - 1] <= m) dp[i][j] = min(dp[i][j], dp[i - 1][j + y[i - 1]]);
    45         }
    46 
    47         rep(j, 1, d[i]) dp[i][j] = INF;
    48         rep(j, u[i], m) dp[i][j] = INF;
    49     }
    50 
    51     ans = INF;
    52     rep(i, 1, m) ans = min(ans, dp[n][i]);
    53     if (ans != INF) return 0, printf("%d
    %d
    ", 1, ans);
    54     int t = q;
    55     dec(i, n, 1){
    56         rep(j, 1, m) ans = min(ans, dp[i][j]);
    57         if (ans != INF) break;
    58         if (u[i] != m + 1) --t;
    59     }
    60 
    61     printf("%d
    %d
    ", 0, t);    
    62     return 0;
    63 }
  • 相关阅读:
    Post请求data参数构造及巧用js脚本显示爬虫进度
    Javascript动态生成的页面信息爬取和openpyxl包FAQ小记
    Selenium实战脚本集—新浪微博发送QQ每日焦点
    linux下如何使用Mysql
    selenium 点击页面链接测试
    功能测试工具Selenium IDE
    JAVA + SELENIUM--环境搭建
    将Sublime Text 2搭建成一个好用的IDE
    Appium(JAVA)Windows 7系统搭建及示例运行
    python 进行web测试
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/6636910.html
Copyright © 2020-2023  润新知