《黑书》递推: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; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。