HDU 5900 QSC and Master (区间DP)

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

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

注意:当Ai和Ai+1被消去后,Ai-1和Ai+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]作为相邻的数也可以被消去。这种情况的讨论非常重要!!!

      代码送上

 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,n)        for(int i(0); i <  (n); ++i)
10 #define rep(i,a,b)        for(int i(a); i <= (b); ++i)
11 #define dec(i,a,b)        for(int i(a); i >= (b); --i)
12 #define for_edge(i,x)        for(int i = H[x]; i; i = X[i])
13
14 const int N    =    100000        +    10;
15 const int M    =    10000        +    10;
16 const int Q    =    1000        +    10;
17 const int A    =    30        +    1;
18
19 typedef long long LL;
20
21 LL f[Q][Q];
22 bool c[Q][Q];
23 bool ret[Q][Q];
24 int T;
25 int n;
26 LL a[Q], b[Q];
27 LL gcd(LL a, LL b){ return b == 0 ? a : gcd(b, a % b); }
28
29
30 int main(){
31     scanf("%d", &T);
32     while (T--){
33         scanf("%d", &n);
34         memset(a, 0, sizeof a);
35         memset(b, 0, sizeof b);
36         memset(c, false, sizeof c);
37         memset(ret, false, sizeof ret);
38         memset(f, 0, sizeof f);
39         rep(i, 1, n) scanf("%lld", a + i);
40         rep(i, 1, n) scanf("%lld", b + i);
41         rep(i, 1, n - 1) rep(j, i + 1, n) if (gcd(a[i], a[j]) != 1) c[i][j] = true;
42         rep(i, 1, n - 1) if (gcd(a[i], a[i + 1]) > 1) ret[i][i + 1] = true;
43         for (int len = 4; len <= n; len += 2){
44             rep(i, 1, n - len + 1){
45                 int j = i + len - 1;
46                 bool flag = false;
47                 if (c[i][i + 1] && ret[i + 2][j]) flag = true;
48                 if (c[j - 1][j] && ret[i][j - 2]) flag = true;
49                 if (c[i][j] && ret[i + 1][j - 1]) flag = true;
50                 for (int k = i + 2; k <= j - 3; k += 2) if (ret[k][k + 1] && ret[i][k - 1] && ret[k + 2][j]){ flag = true; break;}
51                 if (flag) ret[i][j] = true;
52             }
53         }
54
55         rep(i, 1, n - 1) if (c[i][i + 1]) f[i][i + 1] = b[i] + b[i + 1];
56         rep(i, 1, n - 2) f[i][i + 2] = max(f[i][i + 1], f[i + 1][i + 2]);
57         rep(len, 4, n){
58             rep(i, 1, n - len + 1){
59                 int j = i + len - 1;
60                 rep(k, i, j) f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j]);
61                 if (len % 2 == 0){ if (ret[i + 1][j - 1] && c[i][j]) f[i][j] = max(f[i][j], b[i] + b[j] + f[i + 1][j - 1]); }
62                 f[i][j] = max(f[i][j], f[i + 1][j]);
63                 f[i][j] = max(f[i][j], f[i][j - 1]);
64                 if (c[i][i + 1]) f[i][j] = max(f[i][i + 1] + f[i + 2][j], f[i][j]);
65                 if (c[j - 1][j]) f[i][j] = max(f[j - 1][j] + f[i][j - 2], f[i][j]);
66                 rep(k, i + 1, j - 2) if (c[k][k + 1]) f[i][j] = max(f[i][j], f[i][k - 1] + f[k][k + 1] + f[k + 2][j]);
67             }
68         }
69         printf("%lld\n", f[1][n]);
70
71
72     }
73
74
75     return 0;
76
77 }
时间: 2024-10-12 19:13:32

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

hdu 5900 QSC and Master 区间dp

QSC and Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Every school has some legends, Northeastern University is the same. Enter from the north gate of Northeastern University,You are

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

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legends, Northeastern University is the same. Enter from the north gate of Northeastern University,You are facing the main building of Northeastern Universi

Hdu 5900 QSC and Master

给出n对数keyi,vali表示当前这对数的键值和权值,可以操作将连续的两个数合并,如果满足gcd(a[i],a[i+1])>1,得到 的价值是两个数的权值和,每次合并两个数之后,这两个数就会消失,然后旁边的数会接上 比如1 2 3 4 合并了 2 3 则 剩下1 4也可以合并. 处理出任意区间内的所有数是否可以合并 对于当前的[l,r]区间,如果区间[l+1,r-1]可以合并,且gcd(a[l]+a[r])>1的话,则整个区间[l,r]可以合并,价值也就是前缀和 同理处理出其他的情况  [l

HDU 5900 - QSC and Master [ DP ]

题意: 给n件物品,有key和value 每次可以把相邻的 GCD(key[i], key[i+1]) != 1 的两件物品,问移除的物品的总value最多是多少 key : 1 3 4 2  移除34以后12也相邻了,可以移除 分析: 先预处理出所有GCD[l][r], 意味 l <= i <= r的区域可以全部移除, 用记忆化搜索处理 然后 dp[i] 代表到 i 为止可以得到的最大value和 if (G[l][r]) dp[r] = max(dp[r], dp[l-1] + sum[r

HDU 4960 Another OCD Patient 区间dp

区间dp.. T^T一直感觉是n^3,看了题解看来是数据水了么.. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string.h> #define ll long long #define inf 1e8 inline int min(int a, int b){return a<b?a:b;} inline void rdl(ll

hdu 5151 Sit sit sit(区间dp+排列组合)

题目链接:hdu 5151 Sit sit sit 题意: 一共有并排N个椅子, N个学生依次去坐,同时满足3个条件就不能坐下去: 1,该椅子不在最左,不在最右. 2,该椅子左右都有人坐了. 3,左右的椅子不同颜色.求最后N个人都能坐下去,有多少不同的情况. 题解: 考虑区间dp,dp[i][j] = sum(dp[i][k-1] * dp[k+1][j] * c[j - i][k - i])其中满足(v[k-1]==v[k+1]) 表示i到j区间最后来坐k位置,乘组合是因为合并这两段区间的时候

HDU 2476 String painter(区间DP啊)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2476 Problem Description There are two strings A and B with equal length. Both strings are made up of lower case letters. Now you have a powerful string painter. With the help of the painter, you can cha

HDU 2476 String painter (区间DP)

题意:给出两个串a和b,一次只能将一个区间刷一次,问最少几次能让a=b 思路:首先考虑最坏的情况,就是先将一个空白字符串刷成b需要的次数,直接区间DP[i][j]表示i到j的最小次数. 再考虑把a变成b的次数 ans[i]:a从(0,i)变成b(0,i)所需的最小次数 初始化ans[i]=dp[0][i] 如果a[i]==b[i],则ans[i]=ans[i-1]; 由小区间更新到大区间 1 //#pragma comment(linker, "/STACK:167772160")//

hdu 5115 Dire Wolf(区间dp)

Problem Description Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not all, Dire Wolves appear to originate from Draenor. Dire wolves look like normal wolves, but these creatures are of nearly twice th