zoukankan      html  css  js  c++  java
  • 区间DP(hdu5900)

    题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5900

    大意:There are N pairs of numbers,Each pair consists of a key and a value,Now you need to move out some of the pairs to get the score.You can move out two continuous pairs,if and only if their keys are non coprime(their gcd is not one).The final score you get is the sum of all pair’s value which be moved out. May I ask how many points you can get the most?

    N<=300,可用O(n3)算法过,显然是区间dp。

    以区间dp分析,dp[i][j]来自dp[i][k]+dp[k+1][j]转移,还有就是来自本区间(因为本区间在前面是没有计算过的)(如在本题中先中间的消去,然后i与j消去)。

    所以在本题中,只要判断并计算一下本区间的,然后再考虑转移就行了。

    这里判断某区间能否消去,可以用前缀和,虽然我用了麻烦的方法先预处理了区间能否消去。

     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<queue>
     4 #include<string.h>
     5 using namespace std;
     6 typedef long long ll;
     7 
     8 struct Node{
     9     ll k,v;
    10 }node[305];
    11 int cos1[305][305]={0}; //能否消去 
    12 ll dp2[305][305];
    13 ll gcd(ll x,ll y)
    14 {    if(y==0) return x;
    15     return gcd(y,x%y);
    16 }
    17 int main()
    18 {    int T;
    19     scanf("%d",&T);
    20     while(T--)
    21     {    int n;
    22         scanf("%d",&n);
    23         memset(cos1,0,sizeof(cos1));
    24        
    25         memset(dp2,0,sizeof(dp2));
    26         for(int i=1;i<=n;i++)
    27             scanf("%lld",&node[i].k);
    28         for(int i=1;i<=n;i++)
    29             scanf("%lld",&node[i].v);
    30         for(int j=2;j<=n;j++)
    31         for(int i=j-1;i>=1;i--)
    32         {
    33             if((j-i)%2==0) continue;
    34             if((j-i)==1)
    35             {
    36                 if(gcd(node[i].k,node[j].k)!=1) cos1[i][j]=1;
    37             } 
    38             else
    39             {    if(cos1[i+1][j-1]==1&&gcd(node[i].k,node[j].k)!=1) cos1[i][j]=1;
    40                 else
    41                 {    int k;
    42                     for(k=1;i+k+1<j;k++)
    43                     if(cos1[i][i+k]==1&&cos1[i+k+1][j]==1) break;
    44                     if(i+k+1<j)    cos1[i][j]=1;
    45                 }
    46                 
    47             }
    48             
    49         }
    50         
    51     for (int l = 2; l <= n; ++l) 
    52     {
    53     for (int i = 1, j; i <= n - l + 1; ++i) 
    54         {    j = i + l - 1;
    55             if(gcd(node[i].k,node[j].k)!=1) 
    56             {
    57             if((j-i)==1) dp2[i][j]=node[i].v+node[j].v;
    58             if((j-i)>1&&cos1[i+1][j-1]==1) dp2[i][j]=node[i].v+node[j].v+dp2[i+1][j-1];
    59             }
    60             else  dp2[i][j]=0;
    61        
    62         for (int k = i; k < j; ++k) {
    63            dp2[i][j]=max(dp2[i][j],dp2[i][k]+dp2[k+1][j]);
    64         }
    65         
    66         }
    67     }
    68 
    69         printf("%lld
    ",dp2[1][n]);
    70     }
    71     return 0;
    72  
    73 }

    其实代码中两个循环是一个意思,都是枚举所有区间,但要保证在计算某个区间前它的子区间都已计算过。

    开始分析区间dp问题的时候我觉得采用普通dp一样的分析,假设多一单位长度,分析多的这一单位长度的影响,还有子区间都已计算好。。。。

  • 相关阅读:
    移动端性能优化动态加载JS、CSS
    右侧跟踪导航
    JQ+rotate插件实现图片旋转,兼容IE7+ CHROME等浏览器
    什么JSONP
    Web前端开发:什么是页面重回(repaints)与回流(reflow)
    javascript中的eval()函数应用以及要点
    SQL表值参数批量插入
    SQL SERVER 使用 OPENRORWSET(BULK)函数将txt文件中的数据批量插入表中(2)
    SQL SERVER 使用BULK Insert将txt文件中的数据批量插入表中(1)
    一个编程菜鸟的进阶之路(C/C++)
  • 原文地址:https://www.cnblogs.com/lnu161403214/p/8341805.html
Copyright © 2011-2022 走看看