采用数组dp[i][j]。若dp[i][j]==1,则说明放i条直线有j个交点,则只需要把dp[n][i]从i=0到i=190扫一遍,因为20条直线最多有190个交点。
转移为:要求i条直线有多少个交点,则此i条直线可以分为两组,一组是j条平行线,另外一组是i-j条自由线,则此种交法的交点数就为(i-j)*j+k(k为j条自由线的交点数)
PS: DP智商是硬伤。。。。这还是想了好久,参考别人的。。。。
#include <cstdio>
#include <cstring>
using namespace std;
int dp[21][191];
int main()
{
int n;
memset(dp,0,sizeof(dp));
for(int i = 0 ; i < 21 ; i++)
{
dp[i][0] = 1; //初始化,一定有0个交点,所以dp[i][0] == 1
}
for(int i = 1 ; i < 21 ; i++)
{
for(int j = 0 ; j < i ; j++) //j条平行边,剩下i-j条自由边。
{
for(int k = 0 ; k < 191 ; k++) //i-j条自由边是否有k个交点,则有i条直线就可以多一种交法。
{
if(dp[i-j][k] == 1)
{
dp[i][(i-j)*j+k] = 1;
}
}
}
}
while(scanf("%d",&n) != EOF)
{
printf("0");
for(int i = 1; i < 191 ; i++)
{
if(dp[n][i] == 1)
{
printf(" %d",i);
}
}
putchar(10);
}
return 0;
}