1009 QSC and Master
题意:
有n个对,每对一个key一个value,每当你移动两个不互质且相邻的对,这两个相邻对左右的对就会成为相邻对,同时你会得到这两个相邻对的value的和,最终得分就是这些和的和的值,求这个和的最大值
思路:
dp,递归的dp,一定要注意“去掉的相邻对左右的对会成为相邻对”
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
/*
f[i][j] = max{f[i][k]+f[k+1][j], f[k][k+1]+f[i][k-1]+f[k+2][j]};
2^31 > 10^9
*/
using namespace std;
const int N = 305;
//判断是否互质,不互质返回true
__int64 key[N];
__int64 val[N];
__int64 f[N][N];
__int64 my_max(__int64 x, __int64 y){
return x>y?x:y;
}
int gcd(__int64 x, __int64 y){
int temp;
while(y){
temp = x%y;
x = y;
y = temp;
}
return x>1;
}
__int64 dp(int x, int y){
__int64 ans=0;
if(f[x][y] != -1) return f[x][y];
if(x>y || x==y) return f[x][y] = 0;
__int64 ttt = gcd(key[x],key[y]);
if(x+1==y){
if(ttt) return f[x][y] = val[x]+val[y];
else return f[x][y] = 0;
}
if(ttt){
__int64 tmp=0, temp=0;
for(int i=x+1; i<=y-1; i++)
tmp += val[i];
temp = dp(x+1,y-1);
if(tmp == temp)
ans = val[x]+val[y]+tmp;
}
for(int k=x; k<=y-1; k++)
ans = my_max(ans, dp(x,k)+dp(k+1,y));
return f[x][y] = ans;
}
int main(){
int t, n;
scanf("%d", &t);
while(t-->0){
scanf("%d", &n);
memset(f, -1, sizeof(f));
for(int i=1; i<=n; i++)
scanf("%I64d", &key[i]);
for(int i=1; i<=n; i++)
scanf("%I64d", &val[i]);
if(n<=1){
printf("0\n");
continue;
}
printf("%I64d\n", dp(1,n));
}
return 0;
}
反思:
感想:
这道题很有问题呀,我把适当的int改成__int64就过了!
而且改的途中出现了问题,就是如果int的这个变量是题目给的10^9的范围,请务必换成__in64,因为这个我的my_max函数错了……
然后,需要明确的是long long和__int64完全可以互换(在此题中),输出都是%I64d可
1007 odd-even number
典型的数位dp,但是我的数位dp还不是很熟练,所以多加练习后再回来做吧