题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5900
题意:给我们n个数对,我们能够通过去掉相邻且键值不互质的两个数对得到它们的价值,去掉一对之后有可能之前不相邻的就变成了相邻。
这题我们采取的方法是对区间进行dp求解,用dp[L][R]来表示区间L~R之间的最大值,如果两个数不互质,且中间的额数都被取走了,那么这两个数就可以取,再通过不断的缩小区间的大小来求得最大值。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 300+5;
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
LL key[maxn], val[maxn], dp[maxn][maxn];
int n;
LL dfs(int L, int R)
{
if(dp[L][R] != -1) return dp[L][R];
if(L >= R) return dp[L][R] = 0;
LL tmp = gcd(key[L], key[R]),Max=0;
if(L == R-1 && tmp != 1) return dp[L][R] = val[L]+val[R];
if(L == R-1 && tmp == 1) return dp[L][R] = 0;
if(tmp != 1)
{
LL sum = 0;
for(int i=L+1; i<=R-1; i++) sum += val[i];
if(sum == dfs(L+1, R-1)) Max = sum + val[L] + val[R];
}
for(int i=L; i<R; i++) Max = max(Max, dfs(L, i)+dfs(i+1, R));
return dp[L][R] = Max;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
memset(dp,-1,sizeof(dp));
for(int i=0; i<n; i++) scanf("%I64d", &key[i]);
for(int i=0; i<n; i++) scanf("%I64d", &val[i]);
LL ans = dfs(0, n-1);
cout << ans << endl;
}
}