cf839B Game of the rows

非常有趣的一道贪心题。考试期间我是毫无思路,然后今天看作者的题解,哇,真玄学。下面我大概就把作者的题解思路说一下,然后誊写一遍作者的代码


题意大概是这样的,一帮人选座位,要求不同组的不能坐在一起。每一行的座位构成都是这样的:
这里写图片描述
那么显然12 34 45 56 78是邻位。现在给你各组的人数,问能不能满足条件。
好,首先为了粉碎一些天真的想法,我们先举几个蛇皮走位:
1行,2个组,每组4个,方法是这样的:
这里写图片描述
又如,1行4个组,是2 2 2 1,方法:
这里写图片描述


那么作者本人是怎么想的呢?
首先我们将座椅分为两种,一种是4人座,一种是2人座。一共有n排,就先将n排分为n个4人座与2n个2人座。

好,那么假设某一组有k个人。我们优先让他们坐在4人座上,如果没有空余的4人座,就让他们去坐2人座。为什么这样排?因为4人座没有两人座灵活,如果某一组有3个人,那么分在一个4人座、2个2人座是等价的;而如果两个组人数分别为为2,2,分两个两人座是允许的,但没办法放四人座;如果两个组人数分别为1,1,1个4人座与2个2人座也是等价的。所以我们发现,4人座安排上没有两人座方便,所以我们优先四人座。

因此我们的第一步就是遍历让k-4,如果没有两人座就-2。当然,这个过程如果4人座和2人座都满了,那直接超载,别多想。而遍历的终止时机,则是k<=2.现在我们剩下的人只有两种情况:1个人成1组,2个人成1组。

对于两人组的处置,我们优先放2人座。因为如果放到4人座上,就会使得4人座只能放一个人。如果2人座满了,就将4人座拆成一个两人座和一个单人座。实在不行先将两个人拆成两个单人,这样,我们消灭了所有的2人,只剩下一堆的单人成组和一堆座。一个四人座可以充当两个单人座,所以最后的判断就是比较单人剩余数量与(2*4人座数量+2人座数量+单人座数量),比较一下就可以了。

总结一下这个结果是如何得出的。

  • 将每个组的人优先分到4人座上,不够的再分到两人座上,直到剩余1个或2个人
  • 将每个2人组优先分到2人座上,否则将4人座拆为1双1单,否则拆成两个单人
  • 比较最后剩余的可座的座位数与单人的剩余量。

那么代码就呼之欲出了:

#include <bits/stdc++.h>
using namespace std;
#define maxn 10003
int twose,fouse,onese;
int cou[4];
int main(){
    int n,k;
    cin>>n>>k;
    twose=n<<1,fouse=n;
    for(int i=0;i<k;++i){
        int p;cin>>p;
        while(p>=3){//步骤1
            if(fouse>0)
                p-=4,--fouse;
            else if(twose>0)
                p-=2,--twose;
            else{
                cout<<"NO"<<endl;
                return 0;
            }
        }
        if(p>0) cou[p]++;
    }
    while(cou[2]){//步骤2
        if(twose>0)
            --cou[2],--twose;
        else if(fouse>0)
            --cou[2],--fouse,++onese;
        else
            --cou[2],cou[1]+=2;
    }
    if(cou[1]<=onese+twose+2*fouse) cout<<"YES"<<endl;//步骤3
    else cout<<"NO"<<endl;
    return 0;
}

贪心好难啊qwq

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C++实现Game of Life的示例代码: ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; const int ROWS = 20; const int COLS = 60; // 初始化格子 void initializeGrid(bool grid[][COLS]) { srand(time(NULL)); for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { int random = rand() % 10; if (random < 3) { grid[row][col] = true; } else { grid[row][col] = false; } } } } // 显示格子 void displayGrid(bool grid[][COLS]) { for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { if (grid[row][col]) { cout << "*"; } else { cout << " "; } } cout << endl; } } // 计算每个格子周围活细胞的数量 int countNeighbors(bool grid[][COLS], int row, int col) { int count = 0; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { int neighborRow = row + i; int neighborCol = col + j; if (neighborRow >= 0 && neighborRow < ROWS && neighborCol >= 0 && neighborCol < COLS) { if (i != 0 || j != 0) { if (grid[neighborRow][neighborCol]) { count++; } } } } } return count; } // 更新格子 void updateGrid(bool grid[][COLS]) { bool newGrid[ROWS][COLS]; for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { int neighbors = countNeighbors(grid, row, col); if (grid[row][col]) { if (neighbors == 2 || neighbors == 3) { newGrid[row][col] = true; } else { newGrid[row][col] = false; } } else { if (neighbors == 3) { newGrid[row][col] = true; } else { newGrid[row][col] = false; } } } } for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { grid[row][col] = newGrid[row][col]; } } } // 主函数 int main() { bool grid[ROWS][COLS]; initializeGrid(grid); while (true) { system("cls"); // 清屏 displayGrid(grid); updateGrid(grid); } return 0; } ``` 以上代码使用二维布尔数组来表示格子的状态,并且使用函数来完成初始化、显示、计算和更新等操作。在主函数中,我们先使用 `initializeGrid` 函数来随机初始化格子的状态,然后使用 `displayGrid` 函数来显示格子,最后使用 `updateGrid` 函数来更新格子的状态。由于Game of Life是一个无限大的世界,因此我们在这里使用了一个简单的循环来模拟它。 需要注意的是,由于在Windows系统中,清屏需要使用 `system("cls")` 命令,因此以上代码只能在Windows系统中运行。如果你想在其他操作系统中运行该代码,需要使用相应的清屏命令。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值