UVALive4922_Queen Collision

来源:互联网 发布:中科大gpa算法 编辑:程序博客网 时间:2024/05/01 09:37
http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=32&page=show_problem&problem=2923


一开始是想了暴力,即对于每个皇后找到与之冲突的所有皇后,显然,O(n^2)果断是TLE的(皇后的总数不会超过n),然后就要想办法优化,想了排序,想了对于每个点当找到超过8个冲突时可停止查找(因为每个皇后最多与其他8个产生冲突)。。反正就是想了挺久的,走上了这条不归路。。。。
最后的做法,不是我想出来的,是一个与我一开始的想法完全不同的思考方向,不是找每个皇后的所有冲突,而是找所有可能发生冲突的地方有多少个皇后,即计算每一行每一列每条对角线上一共有多少个皇后,如果有k个皇后,就会有k-1对冲突(因为冲突的皇后之间必须无障碍)。这种做法,O(n),而且也不用保存每个皇后的位置,代码也很短。
反思:为什么我总是把问题复杂化。。。。。


代码:
row[x] 表示第x行有几个皇后
col[y] 表示第y列有几个皇后
dia1[x-y] 表示主对角线(把负数部分移到正数部分的后面)

dia2[x+y] 表示副对角线


代码:

#include <cstdio>#include <cstring>using namespace std;const int N = 30000 * 2 + 10;int row[N/2], col[N/2], dia1[N], dia2[N];int main(){    //freopen("a", "r", stdin);    //freopen("b", "w", stdout);    int n, g;    while (scanf("%d", &n) != EOF && n)    {        memset(row, 0, sizeof(row));        memset(col, 0, sizeof(col));        memset(dia1, 0, sizeof(dia1));        memset(dia2, 0, sizeof(dia2));        scanf("%d", &g);        int k, x, y, s, t, tmpx, tmpy;        while (g--)        {            scanf("%d%d%d%d%d", &k, &x, &y, &s, &t);            for (int i = 0; i < k; i++)            {                tmpx = x + i * s;                tmpy = y + i * t;                row[tmpx]++;                col[tmpy]++;                int tmp = tmpx - tmpy;                if(tmp < 0) tmp += 2 * (n-1) + 1;                dia1[tmp]++;                dia2[tmpx+tmpy]++;            }        }        int sum = 0;        for (int i = 1; i <= n; i++)        {            if (row[i]) sum += row[i] - 1;            if (col[i]) sum += col[i] - 1;        }        for (int i = 0; i <= n + n; i++)        {            if (dia1[i]) sum += dia1[i] - 1;            if (dia2[i]) sum += dia2[i] - 1;        }        printf("%d\n", sum);    }}


原创粉丝点击