HDU-5884-Sort

ACM模版

描述

描述

题解

这个题十分有趣,二分 + 贪心。

二分 k ,然后贪心判定是否可以通过。这里判断的过程可以用优先队列优化,每次出 k 个小的,然后合并起来,变为一个大的存入,但是这样会超时,也许用输入输出外挂可以卡过,但是这里有更好的办法,就是用两个队列,先排序将序列进队列 qi1 ,然后每次从 qi1qi2 中取前 k 个最小值,合并后直接入 qi2,这里很容易证明每次入 qi2 的值都比之前入的大,一直到 qi1 为空, qi2 只剩下一个元素时,结束。

这里有一个很大很大的坑,假如枚举的 k ,那么每次合并消耗的是 k1 个,最后合并完后剩下一个,所以总消耗是 n1 个,那么问题来了,如果 (n1) ,会存在零头,也就是说凑不够 k 个,这个零头怎么办呢?肯定不能放在最后合并,我们应该将这个零头放在开头合并,取这零头个数进行合并,也就是取这最小的几个进行合并,后边的就没有什么问题了,按照上边讲的搞就行了。

题猛一看很简单,也能用很简单的手段过,但是这个坑点一般容易忽视,需要特别注意。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;

const int MAXN = 1e5 + 10;

int N, T;
int a[MAXN];
queue<int> qi1, qi2;

bool charge(int k)
{
    while (!qi1.empty())
    {
        qi1.pop();
    }
    while (!qi2.empty())
    {
        qi2.pop();
    }
    for (int i = 1; i <= N; i++)
    {
        qi1.push(a[i]);
    }

    int num = 0, sum = 0, ans = 0;
    if ((N - 1) % (k - 1) != 0)
    {
        num = (N - 1) % (k - 1) + 1;
        for (int i = 1; i <= num; i++)
        {
            sum += qi1.front();
            qi1.pop();
        }
        qi2.push(sum);
        ans += sum;
    }

    while (!qi1.empty())
    {
        sum = 0;
        for (int i = 1; i <= k; i++)
        {
            if (!qi1.empty() && !qi2.empty())
            {
                if (qi1.front() <= qi2.front())
                {
                    sum += qi1.front();
                    qi1.pop();
                }
                else
                {
                    sum += qi2.front();
                    qi2.pop();
                }
            }
            else if (!qi1.empty())
            {
                sum += qi1.front();
                qi1.pop();
            }
            else if (!qi2.empty())
            {
                sum += qi2.front();
                qi2.pop();
            }
        }
        ans += sum;
        qi2.push(sum);
    }
    if (ans > T)
    {
        return false;
    }

    sum = 0;
    num = 0;
    while (!qi2.empty())
    {
        sum += qi2.front();
        qi2.pop();
        num++;
        if (num == k)
        {
            qi2.push(sum);
            ans += sum;
            sum = 0;
            num = 0;
            if (qi2.size() == 1)
            {
                break;
            }
        }
    }
    if (ans > T)
    {
        return false;
    }

    return true;
}

int main()
{
    int t;
    scanf("%d", &t);

    while (t--)
    {
        scanf("%d%d", &N, &T);
        for (int i = 1; i <= N; i++)
        {
            scanf("%d", &a[i]);
        }
        sort(a + 1, a + N + 1);

        int l = 2, r = N, m, ans = 1;
        while (l <= r)
        {
            m = (l + r) >> 1;
            if (charge(m))
            {
                r = m - 1;
                ans = m;
            }
            else
            {
                l = m + 1;
            }
        }

        printf("%d\n", ans);
    }

    return 0;
}
### 关于HDU 1522问题的解题思路 HDU 1522 是杭电 ACM 在线判题系统中的一个问题,通常涉及算法设计与优化。虽然具体题目未提供,但从编号推测其可能属于动态规划、贪心策略或其他常见算法范畴。 #### 动态规划的应用 如果该问题是关于资源分配或者路径寻找,则可以考虑使用动态规划解决。动态规划的核心在于状态转移方程的设计以及边界条件的设定[^1]。以下是基于假设的一个通用框架: ```cpp #include <iostream> #include <vector> using namespace std; const int MAXN = 1e3 + 5; int dp[MAXN][MAXN]; // 定义dp数组存储中间结果 void solve() { int n, m; cin >> n >> m; // 输入数据规模 vector<int> values(n), weights(m); for (int i = 0; i < n; ++i) cin >> values[i]; for (int j = 0; j < m; ++j) cin >> weights[j]; for (int i = 1; i <= n; ++i) { // 遍历物品 for (int j = 1; j <= m; ++j) { // 遍历容量 if (weights[i - 1] > j) { dp[i][j] = dp[i - 1][j]; // 当前物品无法放入背包 } else { dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weights[i - 1]] + values[i - 1]); // 转移方程 } } } cout << dp[n][m] << endl; // 输出最终结果 } int main(){ solve(); } ``` 上述代码展示了如何通过二维 `dp` 数组记录子问题的结果,并逐步构建全局最优解[^2]。 #### 排序技巧 部分情况下,HDU 的某些问题会涉及到简单的排序操作。例如按照 ASCII 值对字符进行升序排列,这可以通过标准库函数轻松完成[^3]: ```cpp #include <algorithm> #include <string> bool cmp(char a, char b){ return a < b; // 自定义比较规则 } int main(){ string s = "cba"; sort(s.begin(), s.end(), cmp); // 使用sort函数并指定比较器 cout << s << endl; // 输出按字典顺序排列后的字符串 } ``` 以上方法适用于需要处理离散型变量的情况,比如字母串重排等问题。 #### 总结 对于 HDU 1522 这类竞赛编程挑战,建议先仔细阅读题目描述,明确输入输出格式后再决定采用何种算法模型求解。无论是动态规划还是其他高效算法,都需要注重时间复杂度分析以满足性能需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值