UVALive4922_Queen Collision

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);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值