題目鏈接
http://acm.hdu.edu.cn/showproblem.php?pid=5900
Problem Description Every school has some legends, Northeastern University is the same.
Recommend wange2014 | We have carefully selected several similar problems for you: 5901 5899 5898 5897 5896 題意:
n 個pair<int , int>,每次可以選相鄰兩個pair。如果他們的first不互質就可以把它們都刪掉,並且獲得second之和的分數,問最大得分。
思路:區間DP,類似於括號匹配的題(一個括號序列,要求添加最少的括號使這個括號序列匹配) 定義dp[i][j] 表示i~j的區間能得的最大分,那麼有狀態轉移方程:dp[i][j]=dp[i][k]+dp[k+1][j] 另外注意特判取兩邊時的情形,即區間 i+1~j-1 都刪除了(判斷條件dp[i+1][j-1]==sum(b[i+1]+....+b[j-1])),如果gcd(a[i],a[j])>1 dp[i][j]=dp[i+1][j-1]+b[i]+b[j];
代碼如下:
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <queue>
#include <cmath>
#include <string.h>
using namespace std;
long long a[305],b[305];
long long dp[305][305];
long long sum[305];
long long GCD(long long a,long long b)
{
return (b==0)?a:GCD(b,a%b);
}
int main()
{
int T,N;
cin>>T;
while(T--)
{
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%lld",&a[i]);
sum[0]=0;
for(int i=1;i<=N;i++)
{
scanf("%lld",&b[i]);
sum[i]=sum[i-1]+b[i];
}
memset(dp,0,sizeof(dp));
for(int len=1;len<N;len++)
{
for(int i=1;i+len<=N;i++)
{
if(sum[i+len-1]-sum[i]==dp[i+1][i+len-1])
{
dp[i][i+len]=dp[i+1][i+len-1];
if(GCD(a[i],a[i+len])>1) dp[i][i+len]+=b[i]+b[i+len];
}
for(int k=i;k<i+len;k++)
{
dp[i][i+len]=max(dp[i][i+len],dp[i][k]+dp[k+1][i+len]);
}
}
}
printf("%lld\n",dp[1][N]);
}
return 0;
}