[算法分享]每日一题2:过整点确定直线条数

[算法分享]每日一题2:过整点确定直线条数

今天这题来自于第十二届蓝桥杯省赛C++A组第二题
在这里插入图片描述
化简下题目描述就是,有n*m个连续的坐标点,问能确定多少条直线。
由于这题的n和m较小,可以考虑枚举任意两点确定直线,然后用set去重。

①用斜截式来枚举

这里需要注意的就是斜率不存在的情况要避开,在最后加上。
以及由于用到了除法,double类型应该会出现精度问题,要做一下处理。

    set<pair<double, double>> s;
    for(int x1 = 0;x1<20;x1++)
        for(int y1=0;y1<21;y1++)
            for(int x2 = 0;x2<20;x2++)
                for (int y2 = 0; y2 < 21; y2++) {
                    if (x1 != x2 && y1 != y2) {
                        double k = (y2 - y1) * 1.0 / (x2 - x1);
                        double b = (y2 * (x2 - x1) - (y2 - y1) * x2) * 1.0 / (x2 - x1);
                        pair<double, double> nline;
                        nline.first = k;
                        nline.second = b;
                        s.insert(nline);
                    }
                }
    cout << s.size() + n + m;

②动态规划

若题目给的n和m更大的话,很明显枚举就不太行了,这里给出一种动态规划的解法,思路是先用容斥原理接触i行j列格子情况下有多少条从坐标0,0发出的射线,然后利用这个可以求出有多少条直线,这是斜率为正的情况,乘以二就把负斜率的算上了,最后加上垂直和水平的直线就是答案了。代码如下

int n = 20, m = 21, dp[30][30], ans[30][30];
int main(){
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++){
			dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1];
			if (__gcd(i,j) == 1) dp[i][j] += 1;
			ans[i][j] = ans[i-1][j] + ans[i][j-1] - ans[i-1][j-1] + dp[i][j] - dp[i/2][j/2];
		}
	cout<<ans[n-1][m-1]*2 + m + n;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值