《黑书》递推:yanghee 的数表uva10202、hdu1270
思路黑书上有,这两道题目,我是用同一个代码ac的,也讲讲我自己的想法吧:
首先a1+a2肯定会等于一个最小的值,然后a1+a3会是次小的值,这样,我们只要求出a1的值,那么枚举a2+a3的值,只要有解,那么可以求出a1的值,将已经求出来的a1、a2、a3两两相加的值去掉,遇到的下一个最小的值就会是a1+a4了,因为a1+a2,a1+a3,a2+a3的值已经被标记了,那么第一个未被标记的值一定会是最小的a1+a4的值,这样a4也出来了,再标记a1+a4,a2+a4,a3+a4.....然后遇到的下一个未被标记的值会是a1+a5........一次类推,然是所有的值两两相加后能在他们的和里找到,说明这是一组可行的组合,输出来就好........
代码:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
int dp[5009],vist[5009],t[60];
int main()
{
int n;
while(scanf("%d",&n)>0&&n)
{
int len=(n-1)*n/2;
for(int i=1;i<=len;i++)
scanf("%d",&dp[i]);
sort(dp+1,dp+len+1);
int w=0;
for(int i=3;i<=len;i++)
{
t[1]=(dp[1]+dp[2]-dp[i])/2;
t[2]=dp[1]-t[1];
t[3]=dp[2]-t[1];
if(t[2]+t[3]!=dp[i]||t[1]*2!=dp[1]+dp[2]-dp[i])
continue;
memset(vist,0,sizeof(vist));
vist[1]=vist[2]=vist[i]=1;
int sum=1;
int w1=0;
for(int j=4;j<=n;j++)
{
while(vist[sum])
sum++;
t[j]=dp[sum]-t[1];
for(int k=1;k<j;k++)
{
int h;
for(h=sum;h<=len;h++)
if(!vist[h]&&t[k]+t[j]==dp[h])
{
vist[h]=1;
break;
}
if(h>len)
{
w1=1;
break;
}
}
if(w1==1)
break;
}
if(w1==0)
{
w=1;
break;
}
}
if(w==0)
printf("Impossible\n");
else
{
for(int i=1;i<n;i++)
printf("%d ",t[i]);
printf("%d\n",t[n]);
}
}
return 0;
}
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号