//这道题的意思很明显呐,状态想出来了 //dp[i][j]表示在前i件物品中挑选j对物品的最小皮料值 //但是想着01背包的样子写,结果wa啦 //然后思索了很久之后,发现自己就状态想出来了,转移方程一塌糊涂 //dp[i][j]表示在前i件物品中挑选j对物品的最小皮料值 //最重要的是要进行排序,升序排列或者降序排列,这样连续取俩相 //邻的所得到的差的平方一定是最小的,因为差值最小 //分两种情况讨论: //1)如果当前的i件物品正好可以凑成j对 //dp[i][j] = dp[i-2][j-1]+get_value(i,i-1); //2) //dp[i][j] = min(dp[i-2][j-1]+get_value(i,i-1),dp[i-1][j]); //其中dp[i-1][j]表示不选第i个物品能凑成j对的最小的疲劳值 //dp[i-2][j]表示选第i个物品(那它一定得和i-1配对,这样才能差 //值最小)能凑成j-1对所能得到的最小的疲劳值 // //注释的代码还是之前错的思路,还是留着给自己一个警醒吧 //哎,继续练吧 //const int inf = 0x3f3f3f3f; //const int maxn = 2008; //ll dp[maxn]; //ll a[maxn]; //int n,k; // //void init(){ // for (int i=1;i<=n;i++) // scanf("%I64d",&a[i]); // memset(dp,inf,sizeof(dp)); // dp[0] = 0; //} // //ll value(int i,int j){ // return (a[i]-a[j]) * (a[i]-a[j]); //} // // //void solve(){ // sort(a+1,a+1+n); // for (int i=1;i<=n;i++){ // for (int j=min(i,2*k);j>=2;j--){ // dp[j] =min(dp[j],dp[j-2]+value(j/2,j/2+1)); // } // } //// for (int i=0;i<=n;i++) //// printf("%I64d ",a[i]); //// puts(""); // printf("%I64d\n",dp[2*k]); //} // //int main() { // freopen("G:\\Code\\1.txt","r",stdin); // while(scanf("%d%d",&n,&k)!=EOF){ // init(); // solve(); // } // return 0; //} #include <algorithm> #include <bitset> #include <cassert> #include <cctype> #include <cfloat> #include <climits> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <functional> #include <iostream> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <stack> #include <vector> #define ceil(a,b) (((a)+(b)-1)/(b)) #define endl '\n' #define gcd __gcd #define highBit(x) (1ULL<<(63-__builtin_clzll(x))) #define popCount __builtin_popcountll typedef long long ll; using namespace std; const int MOD = 1000000007; const long double PI = acos(-1.L); const int inf = 0x3f3f3f3f; template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; } template<class T> inline T lowBit(const T& x) { return x&-x; } template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; } template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; } const int maxn = 2048; int dp[maxn][maxn]; int a[maxn]; int n,k; int cmp(int a,int b){ return a<b; } int get_value(int i,int j){ return (a[i]-a[j]) * (a[i]-a[j]); } void init(){ for (int i=1;i<=n;i++) scanf("%d",&a[i]); a[0] = 0; // for (int i=1;i<=n;i++) // printf("%d ",a[i]); memset(dp,0,sizeof(inf)); sort(a+1,a+1+n,cmp); //for (int i=0;i<n;i++) // dp[0][i]=0; dp[0][0]=0; } void print(){ for (int i=1;i<=n;i++){ for (int j=0;j<=k;j++) printf("%d ",dp[i][j]); puts(""); } } void solve(){ for (int i=2;i<=n;i++){ int f = i/2; for (int j=1;j<=f;j++){ if (i==2*j) dp[i][j] = dp[i-2][j-1]+get_value(i,i-1); else dp[i][j] = min(dp[i-2][j-1]+get_value(i,i-1),dp[i-1][j]); } } printf("%d\n",dp[n][k]); // print(); } int main() { // freopen("G:\\Code\\1.txt","r",stdin); while(scanf("%d%d",&n,&k)!=EOF){ init(); solve(); } return 0; }
原文:http://blog.csdn.net/timelimite/article/details/44906633