P4447-分组

题目传送门

点我

题目思路

类似一个覆盖的问题,有点像积木,统计各个值出现的次数

然后从小到大排列,从最左边的开始选,如果当前的这个数量是比右边的大,那么就停止,比如是1 2 3 3 4.那么肯定是要在3这里停住,拿出分组1 2 3来,然后再3 4 ....的分。

至于证明,显然这是一个最优的子结构

实现略

第一版的代码如下,有问题:

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

class Node
{
public:
    int v;
    int n;
    Node(int v, int n) : v(v), n(n) {}
};

int main()
{
    vector<Node> q;
    priority_queue<int, vector<int>, greater<int>> fq;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        fq.push(x);
    }
    while (!fq.empty())
    {
        Node n(fq.top(), 1);
        fq.pop();
        while (!fq.empty() && fq.top() == n.v)
        {
            n.n++;
            fq.pop();
        }
        q.push_back(n);
    }
    int ss = q.size();
    q.push_back(Node(0, 0));
    int re = 100000;
    Node a = q[0];
    int str = 0;
    while (str != ss)
    {
        int temp = 1;
        a = q[str];
        while (str != ss)
        {
            if (a.n > 1)
                if (a.n <= q[str + temp].n)
                    q[str + temp - 1].n--;
                else
                {
                    q[str + temp - 1].n--;
                    break;
                }
            if (q[str + temp].v == a.v + 1)
            {
                a = q[str + temp];
                temp++;
            }
            else
                break;
        }
        if (temp < re)
            re = temp;
        while ((str != ss && q[str].n == 1 && q[str].v < a.v) || (q[str].v != q[str + 1].v - 1 && str != ss))
            str++;
    }
    cout << re << endl;
    return 0;
}

问题在哪呢,看样例(从别人的题解那里扒的一个,没想到还真跑出bug了):

8

1 2 2 3 3 4 4 5

会输出2,明显不对,因为是1234,2345,应该是4

代码在运行到1234时,退出了,是因为str++的逻辑有问题,应该只跳过1,但是它直接跳到了4

修改方法,最开始的思路有问题,因为分组直接就删掉了这个,所以应该不论是否n>1都应该执行n--操作,n>1改成n>0,因为--之后还大于0的才是需要判断的,最后str++处的n==1条件改成0就好了

于是就AC了

AC代码

#include <iostream>
#include <queue>
#include <vector>

using namespace std;

class Node
{
public:
    int v;
    int n;
    Node(int v, int n) : v(v), n(n) {}
};

int main()
{
    vector<Node> q;
    priority_queue<int, vector<int>, greater<int>> fq;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        int x;
        cin >> x;
        fq.push(x);
    }
    while (!fq.empty())
    {
        Node n(fq.top(), 1);
        fq.pop();
        while (!fq.empty() && fq.top() == n.v)
        {
            n.n++;
            fq.pop();
        }
        q.push_back(n);
    }
    int ss = q.size();
    q.push_back(Node(0, 0));
    int re = 100000;
    Node a = q[0];
    int str = 0;
    while (str != ss)
    {
        int temp = 1;
        a = q[str];
        while (str != ss)
        {
            q[str + temp - 1].n--;
            if (a.n > 0)
                if (!(a.n <= q[str + temp].n))
                    break;
            if (q[str + temp].v == a.v + 1)
            {
                a = q[str + temp];
                temp++;
            }
            else
                break;
        }
        if (temp < re)
            re = temp;
        while ((str != ss && q[str].n == 0 && q[str].v < a.v) || (q[str].v != q[str + 1].v - 1 && str != ss))
            str++;
    }
    cout << re << endl;
    return 0;
}