这个题今天终于解决了,谢谢eoj上shwei大佬的代码呀!
本题链接如下:
https://acm.ecnu.edu.cn/problem/3724/
判断y=x与y=n-1-x两条直线在矩形区域内的整点个数:
思路一:暴力法 x1<=x<=x2计算每个点的y1,y2值判断在不在矩形区域内(时间复杂度大,在eoj上过不了)
思路二:判断矩形区域与直线的交点,每条直线1的个数就是交点的横坐标投影长度(x2-x1+1)或纵坐标的投影长度(y2-y1+1)。这样就转化成求矩形区域和两条直线的交点并求出投影。求交点关键是如何判断直线与矩形是否相交,考虑清楚直线和矩形的位置情况,x1,y1,x2,y2满足什么条件才和矩形区域相交。
注意:若n为奇数时,中心点可能会被重复计算,所以要判断是否包含中心点,若包含需在最终答案中减1。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,x1,y1,x2,y2,sum;
int q;
int main()
{
cin>>n>>q;
for(int i=0;i<q;i++)
{
sum=0;
cin>>x1>>y1>>x2>>y2;
x1++,y1++,x2++,y2++;
//统计对角线
if(x1<=y1){
//矩形在直线上方时
if(x1!=y1){
//若相交分为两种情况:(底边,左侧边),(底边,上侧边)
if(x2-y1>=0)
//综合两种情况取最小值
sum+=min(x2,y2)-y1+1;
}
//肯定相交分为两种情况:(底边,左侧边),(底边,上侧边)
if(x1==y1){
//综合两种情况取最小值
sum+=min(x2,y2)-y1+1;
}
}
//矩形在直线下方时
else{
//先判断是否和直线相交
//若相交:两种情况:(右边,上边),(右边,左侧边)
if(y2-x1>=0){
sum+=min(x2,y2)-x1+1;
}
}
//统计 反对角线
//将考虑的矩形对称
//依据考虑与y=x交点
ll tmp = y1;
y1 = n + 1 - y2;
y2 = n + 1 - tmp;
if(x1<=y1){
//矩形在直线上方时
if(x1!=y1){
//若相交分为两种情况:(底边,左侧边),(底边,上侧边)
if(x2-y1>=0)
//综合两种情况取最小值
sum+=min(x2,y2)-y1+1;
}
//肯定相交分为两种情况:(底边,左侧边),(底边,上侧边)
if(x1==y1){
//综合两种情况取最小值
sum+=min(x2,y2)-y1+1;
}
}
//矩形在直线下方时
else{
//先判断是否和直线相交
//若相交:两种情况:(右边,上边),(右边,左侧边)
if(y2-x1>=0){
sum+=min(x2,y2)-x1+1;
}
}
// 处理中心点是否被重复计算
ll mid = n / 2 + 1;
//若为奇数并且在矩形区域内
if (n & 1 == 1 && (mid >= x1 && mid <= x2 && mid >= n + 1 - y2 && mid <= n + 1 - y1)) sum--;
cout << sum << endl;
}
return 0;
}