The 10th UESTC Programming Contest Final [D hours]
本题大意:有一条点,第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; }