hdu1466计算直线的交点数
2016-11-10 18:33
218 查看
这道题是从HDU课件上看到的,而且是DP的课件。
推导过程来自PPT:
当n = 20 时, 最大的交点数 = 1 + 2 + ... + (n - 1) = n * (n - 1) / 2 = 190
很容易看出前四个答案
n = 0 0
n = 1 0
n = 2 0 1
n = 3 0 2 3 (解释一下: 0是三条直线平行的情况,2是两条直线平行的情况,3是每条之间都不平行于其他直线.)
现在我们把直线分为两组, 一组里面都是平行线a个,一组名字叫做自由线b个,那么 n = a + b,那么答案就是 ans = a组的交点个数+ a个平行线和b个自由线的交点个数 + b组交点个数
现在推导n = 4的情况
(1) 考虑第四条线和三条线平行,那么平行线组里面有4条线,自由线组里面0条线,那么 ans =0 + (4 - 0) * 0 + 0 = 0;
(2)考虑第四条线和两条线平行,那么平行线组里面有3条线,自由线组里面1条线,那么ans =0 + (4 - 1) * 1 + 0 = 3;
(3)考虑第四条线和一条线平行,那么平行线组里面有2条线,自由线组里面2条线,这是自由线组里面有2种情况(参考n = 2时候的情况)
情况1:自由线组里面的直线是平行的 ,所以ans = 0 + (4 - 2) * 2 + 0 = 4
情况2:自由线组里面的直线是相交的,所以ans = 0 + (4 - 2) * 2 + 1 = 5
(4)考虑第四条线与其他线都不平行,那么平行线组里面有1条线,自由线组里面有3条线,这时候自由线组里面有3种情况(参考n = 3的情况)
情况1:自由线组里面的直线都是平行的,所以ans = 0 + (4 - 3) * 3 + 0 = 3;
情况2: 自由线组里面有两条直线是平行的,所以ans = 0 + (4 - 3) * 3 + 2 = 5;
情况3:自由线组里面没有平行的线,所以ans = 0 + (4 - 3) * 3 + 3 = 6;
综上考虑,n = 4的时候有0 3 4 5 6 ,这5种情况的交点数。
我们用f[21][191] 数组来记录所有的情况,如果f[i][j] == 1,说明有i条线的时候,有j个交点。
下面推广到有m条线的时候
(1) 第m条线和m - 1条线平行,那么平行线里面有m条线,自由线组里面有0条线,那么 ans = 0 + (m - 0) * 0 + 0 = 0
(2)第m条线和m - 2条线平行,那么平行线里面有m - 1条线,自由线组里面有1条线,那么ans = 0 + (m - 1) * 1 + 0 = m - 1
....
(r)第m条线和m - r条线平行,那么平行线里面有m - r + 1条线,自由线组里面有r - 1条线,这里分成r - 1 个情况
那么ans = 0 + [m - (r - 1)] * (r - 1) + [n = r - 1时候的交点方案]
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int f[30][200],n,ans[30];
void init(){
memset(f,0,sizeof f);
for(int i = 0;i <= 20;++i)
f[i][0] = 1;
for(int i = 1;i <= 20;++i)
{
for(int j = 1;j < i;++j)
{
for(int k = 0;k < 191;++k)
{
if(f[j][k])
f[i][(i - j) * j + k] = 1;
}
}
}
}
int main(){
init();
while(~scanf("%d",&n)){
printf("0");
for(int i = 1;i <= 190;++i)
if(f
[i]) printf(" %d",i);
printf("\n");
}
return 0;
}
推导过程来自PPT:
当n = 20 时, 最大的交点数 = 1 + 2 + ... + (n - 1) = n * (n - 1) / 2 = 190
很容易看出前四个答案
n = 0 0
n = 1 0
n = 2 0 1
n = 3 0 2 3 (解释一下: 0是三条直线平行的情况,2是两条直线平行的情况,3是每条之间都不平行于其他直线.)
现在我们把直线分为两组, 一组里面都是平行线a个,一组名字叫做自由线b个,那么 n = a + b,那么答案就是 ans = a组的交点个数+ a个平行线和b个自由线的交点个数 + b组交点个数
现在推导n = 4的情况
(1) 考虑第四条线和三条线平行,那么平行线组里面有4条线,自由线组里面0条线,那么 ans =0 + (4 - 0) * 0 + 0 = 0;
(2)考虑第四条线和两条线平行,那么平行线组里面有3条线,自由线组里面1条线,那么ans =0 + (4 - 1) * 1 + 0 = 3;
(3)考虑第四条线和一条线平行,那么平行线组里面有2条线,自由线组里面2条线,这是自由线组里面有2种情况(参考n = 2时候的情况)
情况1:自由线组里面的直线是平行的 ,所以ans = 0 + (4 - 2) * 2 + 0 = 4
情况2:自由线组里面的直线是相交的,所以ans = 0 + (4 - 2) * 2 + 1 = 5
(4)考虑第四条线与其他线都不平行,那么平行线组里面有1条线,自由线组里面有3条线,这时候自由线组里面有3种情况(参考n = 3的情况)
情况1:自由线组里面的直线都是平行的,所以ans = 0 + (4 - 3) * 3 + 0 = 3;
情况2: 自由线组里面有两条直线是平行的,所以ans = 0 + (4 - 3) * 3 + 2 = 5;
情况3:自由线组里面没有平行的线,所以ans = 0 + (4 - 3) * 3 + 3 = 6;
综上考虑,n = 4的时候有0 3 4 5 6 ,这5种情况的交点数。
我们用f[21][191] 数组来记录所有的情况,如果f[i][j] == 1,说明有i条线的时候,有j个交点。
下面推广到有m条线的时候
(1) 第m条线和m - 1条线平行,那么平行线里面有m条线,自由线组里面有0条线,那么 ans = 0 + (m - 0) * 0 + 0 = 0
(2)第m条线和m - 2条线平行,那么平行线里面有m - 1条线,自由线组里面有1条线,那么ans = 0 + (m - 1) * 1 + 0 = m - 1
....
(r)第m条线和m - r条线平行,那么平行线里面有m - r + 1条线,自由线组里面有r - 1条线,这里分成r - 1 个情况
那么ans = 0 + [m - (r - 1)] * (r - 1) + [n = r - 1时候的交点方案]
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int f[30][200],n,ans[30];
void init(){
memset(f,0,sizeof f);
for(int i = 0;i <= 20;++i)
f[i][0] = 1;
for(int i = 1;i <= 20;++i)
{
for(int j = 1;j < i;++j)
{
for(int k = 0;k < 191;++k)
{
if(f[j][k])
f[i][(i - j) * j + k] = 1;
}
}
}
}
int main(){
init();
while(~scanf("%d",&n)){
printf("0");
for(int i = 1;i <= 190;++i)
if(f
[i]) printf(" %d",i);
printf("\n");
}
return 0;
}
相关文章推荐
- HDU1466 计算直线的交点数 【DP】+【经典题】
- HDU1466 计算直线的交点数
- hdu1466 计算直线的交点数
- 计算直线的交点数(hdu1466简单的dp)
- hdu1466 计算直线的交点数
- hdu1466计算直线的交点数
- hdu1466计算直线的交点数
- hdu1466 计算直线的交点数 DP
- 计算直线的交点数(hdu1466简单的dp)
- HDU1466 计算直线的交点数
- HDU1466 计算直线交点(输出各种交点方案)
- hdu1466 计算直线的交点数
- hdu1466 计算直线的交点数(找规律+数学)
- hdu1466计算直线的交点数&2050 折线分割平面【DP】
- HDU1466 计算直线的交点数
- [HDU1466][动态规划DP]计算直线的交点数
- HDU1466 计算直线的交点数
- hdu 2528:Area(计算几何,求线段与直线交点 + 求多边形面积)
- hdoj 1466计算直线的交点数(经典dp)
- hdoj 1466 计算直线的交点数 【经典DP】