不要二

8 篇文章 0 订阅
4 篇文章 0 订阅

问题描述

http://www.nowcoder.com/questionTerminal/1183548cd48446b38da501e58d5944eb

二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。
对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为:
( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根
小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:
每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)

输出描述:
输出一个最多可以放的蛋糕数

输入例子:
3 2

输出例子:
4

笔记

代码1是自己用回溯法写的,这种问题用回溯法完全应付不来规模变大的情况啊。规模变大肯定算不完。

代码2是参考牛客网上牛客9885763号的答案。

其实就是一个数学问题,分整除4,整除2,奇数等几种情况讨论即可。蛋糕位置就是间隔每个2*2的正方形的区域。

情况1:

如果W和H有一个能被4整除,可以发现,放下的正好是整个区域的一半。

W和H都能被4整除

11001100
11001100
00110011
00110011

W和H只有1个能被4整除

11001100
11001100
00110011

或者

11001100
11001100

情况2:

W和H都不能被4整除,但同时能被2整除。

11
11

或者

110011
110011

或者

110011
110011
001100
001100
110011
110011

这种情况,可以W*H/4求出一个多少个2*2大正方形格子。可以看到1个大格子中取1个,3个大格子中取2个,9个大格子中取5个,对应的关系式W*H/4/2+1,最后小格子的数目再*4,就是(W*H/4/2+1)*4

情况3

W和H都不能被4整除,也不能同时被2整除。

1
1

或者

11001
11001

或者

110
110

或者

110
110
001

发现规律
W*H->答案
1->1
2->2
6->4
9->5

W*H->(W*H/2+1)

代码1回溯法

#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;

void place(vector<vector<bool> > &map, int i, int j, const int W, const int H, int &cnt, int &res)
{
        bool up = (i-2>=0 && j>=0 && i-2<W && j<H && map[i-2][j]);//上边放了
        bool down = (i+2>=0 && j>=0 && i+2<W && j<H && map[i+2][j]);//下边放了
        bool left = (i>=0 && j-2>=0 && i<W && j-2<H && map[i][j-2]);//左边放了
        bool right = (i>=0 && j+2>=0 && i<W && j+2<H && map[i][j+2]);//右边放了
        if (up || down || left || right)//任意一个方向放了就不能放
        {
                printf("can not place in (%d, %d)\n", i, j);
                if (i == W-1 && j == H-1)//放到最后一个结束了
                {
                        printf("\n#end here, cnt = %d, res = %d\n\n", cnt, res);
                        return;
                }
                else if (i != W-1 && j == H-1)//换行
                        place(map, i+1, 0, W, H, cnt, res);
                else if (j != H-1)
                        place(map, i, j+1, W, H, cnt, res);
                else
                        ;       
        }
        else//可以选择放也可以选择不放
        {
                for (int p = 0; p < 2; p++)
                {
                        printf("choose to place %d in (%d, %d)\n", p, i, j);
                        map[i][j] = bool(p);
                        cnt += p;
                        res = max(res, cnt);
                        if (i == W-1 && j == H-1)//放到最后一个结束了
                        {
                                printf("\n#end here, cnt = %d, res = %d\n\n", cnt, res);
                                return;
                        }
                        else if (i != W-1 && j == H-1)//换行
                                place(map, i+1, 0, W, H, cnt, res);
                        else if (j != H-1)
                                place(map, i, j+1, W, H, cnt, res);
                        else
                                ;
                        //回溯
                        cnt -= p;
                        map[i][j] = bool(1-p);
                }
        }

}

int main()
{
        int W, H;
        while(cin >> W >> H)
        {
                vector<vector<bool> > map(W, vector<bool>(H, false));
                int cnt = 0;
                int res = 0;
                place(map, 0, 0, W, H, cnt, res);
                cout << res << endl;    
        }
        return 0;
}

代码2数学分析

#include <iostream>
using namespace std;

int main()
{
        int W, H, i, j, cnt = 0;
        cin >> W >> H;
        if (W % 4 == 0 || H % 4 == 0)
                cnt = W * H / 2;
        else if (W % 2 == 0 && H % 2 == 0)
                cnt = (W * H / 4 / 2 + 1) * 4;
        else
                cnt = W * H / 2 + 1;
        cout << cnt << endl;
        return 0;

}


//其实就是一个数学问题,分整除4,整除2,奇数等几种情况讨论即可。蛋糕位置就是间隔每个2*2的正方形的区域。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值