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

题意:给出序列$A_{i}.key$和$A_{i}.value$,若当前相邻的两个数$A_{i}.key$和$A_{i+1}.key$的最大公约数大于1,则可以把这两个数消去,同时消去$A_{i}.value$和$A_{i+1}.value$,每次消去得到的分数为$A_{i}$和$A_{i+1}$的value值,问最大可能得分。

注意:当$A_{i}$和$A_{i+1}被$消去后,$A_{i-1}$和$A_{i+2}$成为了新的相邻的数。若符合条件则可以继续消去。

思路:很明显是区间DP,但是我比赛中如何也A不了。原因有两个:1.没有注意到位运算的低优先级。2.没有把所有情况考虑清楚。

设$f[i][j]$为从第$i$个数到第$j$个数所能得到的最大得分,$j-i+1$从2开始依次枚举,最后枚举到$f[1][n]$(考虑DP的无后效性)

分类讨论即可。先考虑不合并的情况,则$f[i][j]$被$f[i][k]+f[k + 1][j]$依次更新。

          再考虑合并的情况$f[i][j]$可以被$f[i][k] + a[k + 1] + a[k + 2] + f[k +3][j]$更新。

          特殊情况讨论:当$a[i + 1]$到$a[j - 1]$中所有的数都可以被消去,则$a[i]$和$a[j]$作为相邻的数也可以被消去。这种情况的讨论非常重要!!!

      代码送上

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional> using namespace std; #define REP(i,n) for(int i(0); i < (n); ++i)
#define rep(i,a,b) for(int i(a); i <= (b); ++i)
#define dec(i,a,b) for(int i(a); i >= (b); --i)
#define for_edge(i,x) for(int i = H[x]; i; i = X[i]) const int N = + ;
const int M = + ;
const int Q = + ;
const int A = + ; typedef long long LL; LL f[Q][Q];
bool c[Q][Q];
bool ret[Q][Q];
int T;
int n;
LL a[Q], b[Q];
LL gcd(LL a, LL b){ return b == ? a : gcd(b, a % b); } int main(){
scanf("%d", &T);
while (T--){
scanf("%d", &n);
memset(a, , sizeof a);
memset(b, , sizeof b);
memset(c, false, sizeof c);
memset(ret, false, sizeof ret);
memset(f, , sizeof f);
rep(i, , n) scanf("%lld", a + i);
rep(i, , n) scanf("%lld", b + i);
rep(i, , n - ) rep(j, i + , n) if (gcd(a[i], a[j]) != ) c[i][j] = true;
rep(i, , n - ) if (gcd(a[i], a[i + ]) > ) ret[i][i + ] = true;
for (int len = ; len <= n; len += ){
rep(i, , n - len + ){
int j = i + len - ;
bool flag = false;
if (c[i][i + ] && ret[i + ][j]) flag = true;
if (c[j - ][j] && ret[i][j - ]) flag = true;
if (c[i][j] && ret[i + ][j - ]) flag = true;
for (int k = i + ; k <= j - ; k += ) if (ret[k][k + ] && ret[i][k - ] && ret[k + ][j]){ flag = true; break;}
if (flag) ret[i][j] = true;
}
} rep(i, , n - ) if (c[i][i + ]) f[i][i + ] = b[i] + b[i + ];
rep(i, , n - ) f[i][i + ] = max(f[i][i + ], f[i + ][i + ]);
rep(len, , n){
rep(i, , n - len + ){
int j = i + len - ;
rep(k, i, j) f[i][j] = max(f[i][j], f[i][k] + f[k + ][j]);
if (len % == ){ if (ret[i + ][j - ] && c[i][j]) f[i][j] = max(f[i][j], b[i] + b[j] + f[i + ][j - ]); }
f[i][j] = max(f[i][j], f[i + ][j]);
f[i][j] = max(f[i][j], f[i][j - ]);
if (c[i][i + ]) f[i][j] = max(f[i][i + ] + f[i + ][j], f[i][j]);
if (c[j - ][j]) f[i][j] = max(f[j - ][j] + f[i][j - ], f[i][j]);
rep(k, i + , j - ) if (c[k][k + ]) f[i][j] = max(f[i][j], f[i][k - ] + f[k][k + ] + f[k + ][j]);
}
}
printf("%lld\n", f[][n]); } return ; }

HDU 5900 QSC and Master (区间DP)的更多相关文章

  1. HDU 5900 QSC and Master 区间DP

    QSC and Master Problem Description   Every school has some legends, Northeastern University is the s ...

  2. 2016 年沈阳网络赛---QSC and Master(区间DP)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legend ...

  3. HDU 5900 QSC and Master

    题目链接:传送门 题目大意:长度为n的key数组与value数组,若相邻的key互斥,则可以删去这两个数同时获得对应的两 个value值,问最多能获得多少 题目思路:区间DP 闲谈: 这个题一开始没有 ...

  4. HDU 5900 - QSC and Master [ DP ]

    题意: 给n件物品,有key和value 每次可以把相邻的 GCD(key[i], key[i+1]) != 1 的两件物品,问移除的物品的总value最多是多少 key : 1 3 4 2  移除3 ...

  5. hdu 4597 + uva 10891(一类区间dp)

    题目链接:http://vjudge.net/problem/viewProblem.action?id=19461 思路:一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r] ...

  6. HDU 2476 String painter (区间DP)

    题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成 ...

  7. hdu_5900_QSC and Master(区间DP)

    题目链接:hdu_5900_QSC and Master 题意: 有n个数,每个数有个key值,有个val,如果相邻的两个数的key的gcd大于1那么就可以得到这两个数的val的和,现在问怎么取使得到 ...

  8. HDU 4597 Play Game(区间DP(记忆化搜索))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 题目大意: 有两行卡片,每个卡片都有各自的权值. 两个人轮流取卡片,每次只能从任一行的左端或右端 ...

  9. HDU 5151 Sit sit sit 区间DP + 排列组合

    Sit sit sit 问题描述 在一个XX大学中有NN张椅子排成一排,椅子上都没有人,每张椅子都有颜色,分别为蓝色或者红色. 接下来依次来了NN个学生,标号依次为1,2,3,...,N. 对于每个学 ...

随机推荐

  1. 【LoadRunner】LR编写Dubbo协议脚本

    一.Dubbo服务简介 Dubbo是一个分布式服务架构,把核心业务抽取出来作为独立的服务,使前端应用能更快速和稳定的响应. Dubbo服务工作原理:服务提供方提供接口,并提供接口的实现,提供方注册服务 ...

  2. 小程序使用Canvas画饼图

    先上效果图 -------------------------------------------------------------wxml代码开始------------------------- ...

  3. 用Python实现基于Hadoop Stream的mapreduce任务

    用Python实现基于Hadoop Stream的mapreduce任务 因为Hadoop Stream的存在,使得任何支持读写标准数据流的编程语言实现map和reduce操作成为了可能. 为了方便测 ...

  4. ZOJ 3606 Lazy Salesgirl ( 线段树 + 思路 )

    卖切糕的小女孩 http://www.cnblogs.com/wuyiqi/archive/2012/04/28/2474672.html #include <cstdio> #inclu ...

  5. C#利用VFW实现摄像头程序

    最近在搞这个考试监控,找来VFW的资料,胡编乱凑而成. VFW全称为Video for Windows,是微软提供的,内嵌windows系统. 首先定义一个VideoAPI类. 首先调用avicap3 ...

  6. 如何出发匿名映射呀【log】

    malloc-9711 [002] .... 40794.642938: mm_vmscan_lru_shrink_inactive: nid=0 zid=1 nr_scanned=3 nr_recl ...

  7. BZOJ 1483:[HNOI2009]梦幻布丁(链表+启发式合并)

    [HNOI2009]梦幻布丁 Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一 ...

  8. BZOJ1877 [SDOI2009]晨跑 【费用流】

    题目 Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他 坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道 ...

  9. GDI+ 双缓存 和 刷新桌面(F5)

    GDI+双缓存 POINT currentPoint; GetCursorPos(&currentPoint); HWND hWnd = ::GetDesktopWindow(); int n ...

  10. mysql如何更改character-set-server默认为latin1

    运行环境:win10 mysql版本:MYSQL5.7免安装版(或解压版) 今天在学习mysql字符集有关乱码的知识 然后发现了latin1的字符集编码格式,虽然命令行窗口改变很容易,只需两行命令 s ...