Uva 10271 Chopsticks

题意:从给定的序列中选出一定数目的三元组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 }
posted @ 2012-11-30 21:21  silver__bullet  阅读(213)  评论(0编辑  收藏  举报