将筷子长度从长到短排列后,就可以忽略z的影响了(对于每一对(x,y)总可以保证有大于其得z);
然后定义状态dp[i][j]表示前i只筷子中凑成j对的最小代价,然后:
如果j<3*i 则dp[i][j]=dp[i-1][j]
如果j>=3*i 对于第i只筷子可以选取构成第j对(与i-1只筷子构成第j个(x,y)),当然也可以不选;
则dp[i][j]=min(dp[i-1][j],dp[i-2][j]+w(a[i],a[i-1]))
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define INF 0x3fffffff int a[10000]; int dp[5500][1100]; int n,k; void input() { scanf("%d%d",&k,&n); for(int i=n;i>=1;i--) scanf("%d",&a[i]); } void solve() { for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) { dp[i][j]=INF; if(j==0) dp[i][0]=0; } for(int i=1;i<=n;i++) for(int j=1;j<=k+8;j++) { dp[i][j]=dp[i-1][j]; if(i>=j*3) { dp[i][j]=min(dp[i][j],dp[i-2][j-1]+(a[i]-a[i-1])*(a[i]-a[i-1])); } } printf("%d\n",dp[n][k+8]); } int main() { int t; scanf("%d",&t); while(t--) { input(); solve(); } return 0; } </span>
原文地址:http://blog.csdn.net/acm_lkl/article/details/43056419