• HDU5900-QSC and Master-区间DP+区间覆盖DP


    地址 http://acm.hdu.edu.cn/showproblem.php?pid=5900

    2016ICPC沈阳赛区网络赛

    题意:一个队列,每个点有key[i]和value[i],位置相邻且key不互质的两个点可以被取走,取走后,剩下点自动连接起来。

        问取走的value和最大

    题解:1.对于所有的区间,用区间DP求出能否 整个 区间取走

          枚举区间长度

          对于[s,e] 的区间,要么由两个比这短的区间拼凑而成,要么s和e可以不互质,且[s+1,e-1]可以取走,特判长度为2的时候。

       2.对于所有能取走的区间,有区间覆盖(覆盖一次)问题

       3.DP解决问题2

          对于所有区间按照终点排序

          对于不是终点的i,dp[i] = dp[i-1]

          对于是终点的i,dp[i] = max( dp[ i - 1 ] , { E.Svalue | E.end == i } )

          坐标轴上的单向最短(长)路问题和这个类似

    沈阳站赛前复习,希望自己沈阳加油。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 long long a[333];
     7 long long b[333];
     8 long long sum[333];
     9 long long dp[333];
    10 struct Edge
    11 {
    12     int s,e;
    13     long long val;
    14 }E[93333];
    15 int ife[333][333];
    16 long long gcd(long long aa, long long bb)
    17 {
    18         return bb == 0 ? aa : gcd(bb,aa % bb);
    19 }
    20 bool com(Edge A,Edge B)
    21 {
    22         return A.e < B.e;
    23 }
    24 void addedge(int s, int e)
    25 {
    26     ife[s][e] = 1;
    27     E[cnt].s = s;
    28     E[cnt].e = e;
    29     E[cnt].val = sum[e] - sum[s-1];
    30     cnt++;
    31 }
    32 int main()
    33 {
    34      int T;
    35      //freopen("in.txt","r",stdin);
    36      cin >> T;
    37      while (T--)
    38      {
    39         memset(E,0,sizeof(E));
    40         memset(ife,0,sizeof(ife));
    41         memset(dp,0,sizeof(dp));
    42         sum[0] = 0;
    43         int N;
    44         cin >> N;
    45         for (int i = 1; i<= N; i++)
    46         {
    47             scanf("%lld",&a[i]);
    48         }
    49         for (int i = 1; i<= N; i++)
    50         {
    51             scanf("%lld",&b[i]);
    52             sum[i] = sum[i-1] + b[i];
    53         }
    54         int cnt = 1;
    55         //区间DP建边
    56         //如果s,e之间 能通过某种方式全部取出,那么s,e区间建边
    57         for (int i = 1; i<=N; i+=2)
    58         {
    59             for (int s = 1; s+i<=N; s++)
    60             {
    61                 int e = s+i;
    62                 if (ife[s][e] == 1) continue;
    63                 if (gcd(a[s],a[e]) != 1LL && (i == 1 || ife[s+1][e-1] == 1))
    64                 {
    65                     addedge(s,e);
    66                     continue;
    67                 }
    68                 for (int l = s + 1 ;l <= e-2; l += 2 )
    69                 {
    70                     if (ife[s][l] == 1 && ife[l+1][e] == 1)
    71                     {
    72                         addedge(s,e);
    73                         break;
    74                     }
    75                 }
    76             }
    77         }
    78         //每个点只能被选一次,转换为区间一次性覆盖,所有的区间都已经经过区间dp求出
    79         //区间一次性覆盖 可以用DP求
    80         sort(E+1,E+cnt,com);
    81         for (int i = 1; i<cnt;)
    82         {
    83             int te = E[i].e;
    84             while (E[i].e == te)
    85             {
    86                 dp[te] = max(dp[te],dp[E[i].s-1] + E[i].val);
    87                 i++;
    88             }
    89             for (int j = te+1 ; j <= E[i].e ; j++)
    90                 dp[j] = dp[j-1];
    91         }
    92         //此处不要输出dp[N],因为dp的范围就是最后一条边的终点
    93         cout << dp[E[cnt-1].e] <<endl;
    94      }
    95 }
  • 相关阅读:
    onTouchEvent的参数详解
    test
    List泛型自定义排序
    unity3d camera.culling mask
    云计算实验一
    软件设计——职责链模式之审批处理
    sqlserver配置sa用户
    软件设计——模板方法模式之对数据库的操作
    flask入门
    课程总结+申请加分
  • 原文地址:https://www.cnblogs.com/HITLJR/p/5974764.html
Copyright © 2020-2023  润新知