题意:
求n个数中k组数,每组2个数,使得每组数之差的平方和最小。
TLE的代码:
思想:1 先排序,把相同的处理掉,并标记被处理的位置,然后遍历数组,每次找未被处理的数据中两个数之差最小的数,加到ans中,直到得到k组数据。很遗憾,被TLE了。
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int a[2005];
int v[1<<15];
int main()
{
int n,k;
while(cin>>n>>k)
{
memset(v,0,sizeof(v));
for(int i=0; i<n; ++i)
cin>>a[i];
sort(a,a+n);
int ans=0;
for(int i=0; i<=n-2; i+=2)
{
if(a[i]==a[i+1])
{
ans++;
v[i]=1;
v[i+1]=1;
}
else
{
i=i-1;
}
if(ans==k)
{
break;
}
}
k=k-ans;
if(k==0)
{
cout<<0<<endl;
continue;
}
//cout<<k<<endl;
int m,nn,min=1000,tem,anss=0;
for(int i=1; i<=k; ++i)
{
min=1000;
for(int j=0; j<n-1;)
{
if(v[j]==0)
for(int l=j+1; l<n; ++l)
{
if(v[l]==0)
{
tem=a[l]-a[j];
if(tem<min)
{
min=tem;
m=j;
nn=l;
}
j=l;
break;
}
}
}
v[m]=1;
v[nn]=1;
anss+=min*min;
//cout<<min<<endl;
}
cout<<anss<<endl;
//cout<<min<<endl;
}
return 0;
}
dp代码:
dp思维就是找状态方程,dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1])),就是dp[m][2*m]的值是可以确定的,可以找到dp[m][2*m+1]与dp[m][2*m],dp[m-1][2*m-1]的关系。
#include<iostream>
#include<string.h>
#include<algorithm>
#define N 2005
using namespace std;
int a[N];
int dp[N/2][N];
//初始化
void init(int k)
{
int aa=0;
for(int i=2; i<=2*k; i+=2)
{
aa+=(a[i]-a[i-1])*(a[i]-a[i-1]);
dp[i/2][i]=aa;
}
}
//dp方程 dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]));
int work(int n,int m)
{
init(m);
for(int i=1; i<=m; i++)
{
for(int j=2*i+1; j<=n; j++)
{
dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(a[j]-a[j-1])*(a[j]-a[j-1]));
}
}
return dp[m][n];
}
int main()
{
int n,k;
while(cin>>n>>k)
{
memset(dp,0,sizeof(dp));
for(int i=1; i<=n; ++i)
cin>>a[i];
sort(a+1,a+n+1);
int ans;
ans=work(n,k);
cout<<ans<<endl;
}
return 0;
}