您的位置:首页 > 其它

EOJ3346-皇后问题

2018-03-19 16:51 218 查看

题目

http://acm.ecnu.edu.cn/problem/3346/

Description:

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

八皇后问题可以推广为更一般的 n 皇后摆放问题:这时棋盘的大小变为 n×n,而皇后个数也变成 n。

现在给你 n 个皇后的位置座标,问总共有多少对皇后互相冲突。

Iuput:

第一行一个整数 n,表示有 n 个皇后。

接下来 n 行,每行两个整数 x,y (1≤x,y≤n),中间用空格分开,表示 n 个皇后的坐标。

数据保证不会有两个皇后在同一个地方。

数据规模约定:

对于 60% 的数据,1≤n≤100。

对于 100% 的数据,1≤n≤10^5。

Output:

输出一个整数,表示有多少对皇后互相冲突。

Examples input:

3

1 1

1 2

1 3

Examples output:

3

思路

解法一:把每个点(皇后)的位置保存下来,然后两重循环判一下各个点是否存在冲突:X1 == X2 或 Y1 == Y2 或 |X1-X2| == |Y1-Y2|,累加存在冲突的点对,最后再输出。时间复杂度O(n^2)。这样只能过60%的数据,当输入数据过多时便会超时。

代码一

#include <bits/stdc++.h>

using namespace std;

#define N 100001

struct point
{
int x, y;
point(){}
point(int xx, int yy):x(xx), y(yy){}

};
vector<point> P;

int main()
{
int n;
cin >> n;
int x, y;
for(int i = 0; i < n; i++)
{
cin >> x >> y;
P.push_back(point(x, y));
}
int ans = 0;
for(int i = 0; i < P.size(); i++)
{
for(int j = i + 1; j < P.size(); j++)
{
if(P[i].x == P[j].x || P[i].y == P[j].y || (abs(P[i].x - P[j].x) == abs(P[i].y - P[j].y)))
ans++;
}
}
cout << ans <<endl;
return 0;
}


解法二:定义四个数组,分别保存同一行、列、副对角线、主对角线包含的皇后个数,然后一次遍历四个数组计算冲突的皇后,累加冲突总数,最后输出。时间复杂度O(n)。

代码二

#include <bits/stdc++.h>

using namespace std;
#define N 100010
typedef long long ll;

ll row
;//行
ll col
;//列
ll dia1[2*N];//副对角线 y = -x + b
ll dia2[2*N];//主对角线 y =  x + b

int main()
{
int n;
cin >> n;
if(n == 1)
cout << 0 << endl;
else
{
int x, y;
for(int i = 0; i < n; i++)
{
cin >> x >> y;
row[x]++;
col[y]++;
dia1[x+y]++;
dia2[y-x+N]++;//+N用于偏移 防止数组下标为负
}
ll ans = 0;
for(int i = 0; i < N; i++)
{
if(row[i] >= 2)
ans += row[i] * (row[i] - 1) / 2;//计算每行冲突数
if(col[i] >= 2)
ans += col[i] * (col[i] - 1) / 2;//计算每列冲突数
}
for(int i = 1; i < 2*N; i++)
{
if(dia1[i] >= 2)
ans += dia1[i] * (dia1[i] - 1) / 2;//计算每副对角线冲突数
if(dia2[i] >= 2)
ans += dia2[i] * (dia2[i] - 1) / 2;//计算每主对角线冲突数
}
cout << ans << endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息