您的位置:首页 > 其它

动态规划入门 HDU 1466-计算直线的交点数

2016-12-09 16:06 363 查看
题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1466

思路分析:

这道题是LCY老师课件上的热身题,我想了好久都没弄明白,直到看了别人的题解,之前一直在找第i条直线与第i-1条直线的关系。主要是方案数的存储没有搞明白,没有想到利用交点数去存储不同的情况,这种做法还有一个好处,可以自动去重。

状态转移的关键是:第i条直线与r条自由直线相交时,交点数=平行线条数*自由直线条数+r条自由直线本身的焦点数=(i-r)*r+k。同时可以从这个递推式发现问题分解后的子问题就是n条直线的交点个数的所有可能情况。找到状态转移方程之后,考虑如何存储,一开始想的是用dp[i][r]存,其实这样计算出来的是与r条自由直线相交的所有可能情况焦点数之和。而大家采用的方法是用dp[i][k](i条直线相交是否拥有k个交点的可能性)。

关于递推式的推导:(以下推导内容摘自LCY老师课件)

容易列举出N=1,2,3的情况:

0

0,1

0,2,3

如果已知<N的情况,我们来分析加入第N条直线的情况(这里N=4):

1、第四条与其余直线全部平行 => 无交点;

2、第四条与其中两条平行,交点数为(n-1)*1+0=3;

3、第四条与其中一条平行,这两条平行直线和另外两点直线的交点数为(n-2)*2=4,而另外两条直线既可能平行也可能相交,因此可能交点数为:

                   (n-2)*2+0=4    或者         (n-2)*2+1=5     

4、 第四条直线不与任何一条直线平行,交点数为:

      (n-3)*3+0=3   或者 (n-3)*3+2=5    或者 (n-3)*3+3=6

即n=4时,有0个,3个,4个,5个,6个不同交点数。

代码实现:

#include"cstdio"
using namespace std;
int dp[22][193]={0};//数组初始化为0
int main()
{
int n,num;
for(int i=0;i<=20;i++)//不管有几条直线,只要全部平行,0个交点的方案就存在
dp[i][0]=1;
for(int i=1;i<=20;i++)//题目要求最大求到20,i代表共有i条直线
{
for(int r=0;r<=i;r++)//i与r条自由直线相交,r条直线可能相交也可能不相交
{
num=r*(r-1)/2;//r条直线最多有num个交点
for(int k=0;k<=num;k++)
{
if(dp[r][k])//i-r条直线与r条直线相交交点个数=(i-r)*r+k(k为r条直线相交交点个数可能值)
dp[i][(i-r)*r+k]=1;
}
}
}
while(~scanf("%d",&n))
{
num=n*(n-1)/2;
printf("0");
for(int i=1;i<=num;i++)
{
if(dp
[i])
printf(" %d",i);
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: