本题大意:有一条点,第i点与第i+1点之间有路i,第k次走过路i获得的愉悦值是ai-(k-1)*bi,保证愉悦值为正,求如何走可以使得愉悦值最大
分析:考虑起点i和重点j,可以假设i<=j,那么i左边的路必定走过偶数次,j右边的路必定走过偶数次,i与j之间的路必定走过奇数次,然后DP即可。
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int oo=100000000;
int f[200][200][200],g[200][200],h[200][200],a[200],b[200],c[200][200];
int main()
{
int num;
scanf("%d",&num);
for (int time=1; time<=num; time++)
{
int i,j,k,t,n,d;
scanf("%d%d",&n,&d);
for (i=0; i<n; i++)
{
scanf("%d%d",&a[i],&b[i]);
c[i][0]=0;
for (j=1; j<=d; j++)
c[i][j]=a[i]-(j-1)*b[i]+c[i][j-1];
}
for (i=0; i<=n; i++)
for (j=0; j<=n; j++)
for (k=0; k<=d; k++)
{
f[i][j][k]=-oo;
g[i][k]=-oo;
h[j][k]=-oo;
}
for (i=0; i<n; i++)
for (j=1; j<=d; j+=2)
f[i][i+1][j]=c[i][j];
for (i=2; i<=n; i++)
for (j=0; j+i<=n; j++)
for (k=i; k<=d; k+=2)
for (t=1; (k-t)>=i-1; t+=2)
if (f[j][j+i][k]<f[j+1][j+i][k-t]+c[j][t])
f[j][j+i][k]=f[j+1][j+i][k-t]+c[j][t];
for (i=2; i<=d; i+=2) {g[1][i]=c[0][i]; h[n-1][i]=c[n-1][i];}
for (i=1; i<=n; i++) {g[i][0]=0; h[n-i][0]=0; f[i][i][0]=0;}
f[0][0][0]=0;
for (i=2; i<=n; i++)
for (j=2; j<=d; j+=2)
for (k=2; k<=j; k+=2)
{
if (g[i][j]<g[i-1][j-k]+c[i-1][k])
g[i][j]=g[i-1][j-k]+c[i-1][k];
if (h[n-i][j]<h[n-i+1][j-k]+c[n-i][k])
h[n-i][j]=h[n-i+1][j-k]+c[n-i][k];
}
int ans=-oo;
for (i=0; i<=n; i++)
for (j=i; j<=n; j++)
for (k=0; k<=d; k+=2)
for (t=0; t+k<=d; t+=2)
if (ans<g[i][k]+h[j][t]+f[i][j][d-k-t])
ans=g[i][k]+h[j][t]+f[i][j][d-k-t];
cout<<"Case #"<<time<<": "<<ans<<endl;
}
return 0;
}