题意:从给定的序列中选出一定数目的三元组x,y,z(x<=y<=z),使得所有三元组中(x-y)^2之和最小
解法:解法类似于hdu搬寝室那个题,但是这里多了一个z的限制,对于z的处理,我们可以把这个序列按照降序排列,这样的话就能消除z的影响.
为什么呢?想一下状态转移方程,dp[i][j]=min(dp[i-1][j],dp[i-2][j-1]+(s[i]-s[i-1])*(s[i]-s[i-1]));
也就是说dp[i][j]的值可能在求dp[i-1][j]时已经得到了,而在这里,我们可以通过"j<=i/3"这个限制保证不会选到最大的...
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 5010 5 #define M 1010 6 using namespace std; 7 int s[N],dp[N][M]; 8 int sqr(int a){ 9 return a*a; 10 } 11 int main(){ 12 int t,n,m; 13 scanf("%d",&t); 14 while(t--){ 15 scanf("%d%d",&m,&n); 16 for(int i=n;i>=1;i--)scanf("%d",&s[i]); 17 for(int i=0;i<=n;i++) 18 for(int j=0;j<=m+8;j++) 19 dp[i][j]=1<<30; 20 for(int i=0;i<=n;i++)dp[i][0]=0; 21 for(int i=1;i<=n;i++) 22 for(int j=0;j<=i/3&&j<=m+8;j++){ 23 int a,b; 24 a=b=1<<30; 25 if(i-1>=3*j)a=dp[i-1][j]; 26 if(i-2>=3*(j-1))b=dp[i-2][j-1]+sqr(s[i]-s[i-1]); 27 dp[i][j]=min(a,b); 28 } 29 printf("%d\n",dp[n][m+8]); 30 } 31 return 0; 32 }