/题目:HD1466-计算直线交点数
//连接:http://acm.hdu.edu.cn/showproblem.php?pid=1466
/*解题思路:可用DP解决的问题,状态能转移方程也比较容易发现。
简单分析一下:n=5的情况,当加入第5条时。
1、与前四条都平行,则(n-0)*0+0;
2、与其中三条平行,则(n-1)*1+0;
3、两条,则(n-2)*2+0、(n-2)*2+1;
4、一条,则(n-3)*3+0、2、3;//三种
5、都平行,则(n-4)*4+0、3、4、5、6;
不难发现状态转移方程为f[n,r]=(n-r)*r+f[r,r'];
f[n,r]表示n条时的所有可能情况
n-r平行的边数,0<=r'<=r-1
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=20;
int main()
{
int a[N+1][700];//694 is the result of calculate,so i use 700!
int n;
while(scanf("%d",&n)!=EOF)
{
int i,j,k;
a[1][0]=0;a[0][1]=1;
for(i=2; i<=n; i++)
{
a[i][0]=0;
a[0][i]=1;//it is used to count the number of the cases.
for(j=1; j<i; j++)
{
int t=(i-j)*j;//f[m,r]=f[r,r']+(m-r)*r.it's the zhuangtaizhuanyifangcheng.
for(k=0; k<a[0][j]; k++)
{
a[i][k+a[0][i]]=a[j][k]+t;
}
a[0][i]+=k;
}
sort(a[i],a[i]+a[0][i]);//sort the array!
int t=-1;
k=0;
for(j=0; j<a[0][i]; j++)
{
if(t!=a[i][j])//erase the same number.
{
t=a[i][j];
a[i][k++]=t;
}
}
for(j=k; j<a[0][i]; j++)
a[i][k]=0;
a[0][i]=k;
}
for(i=0; i<a[0][n]-1; i++)
printf("%d ",a[n][i]);
printf("%d\n",a[n][i]);
}
return 0;
}