Hdu 1387 Team Queue[队列 || 链表]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1387

题目的意思很贴近生活,说有n个队,每个队有a1, a2,a3 ....an个人,队内人互相认识,且在排队的时候可以插队。这简直就是生活啊。

主要两个操作:

ENQUEUE x 标号为x的人进队
DEQUEUE 队头的人出队
让你输出出队顺序。

自己在9月份用链表写,怎么也写不过,今天又遇到了他,终于用链表给a了。

现在看来,那时候的错主要是,一个head变量没有更新导致一直wa。

链表code:

<span style="font-size:18px;">
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
using namespace std;

struct Node
{
    int type;
    int num;
    Node *next;
    Node(){
        type = -1;
        num = -1;
        next = NULL;
    }
    Node(int x, int y){
        type = x;
        num = y;
        next = NULL;
    }
} *root, *tail;

const int N = 1e6 + 5;
const int M = 1e3 + 4;
int hash[N];
Node *head[M];

void  insert(int t, int x){
    // 如果删去的是头,那么head不应该是变了吗。。?? good
    if(head[t] == NULL) {
        tail -> type = t;
        tail -> num = x;
        head[t] = tail;
        tail -> next = new Node();
        tail = tail -> next;
    }
    else {
        Node *p = head[t], *tmp;
        while(p-> next != tail && p -> next -> type == t){
            p = p -> next;
        }// tail may changed..
        if(p -> next == tail){
            tail -> num = x;
            tail -> type = t;
            tail -> next = new Node();
            tail = tail -> next;
        }
        else {
            tmp = p -> next;
            p -> next = new Node(t, x);
            p -> next -> next = tmp;
        }
    }
    return ;
}

//void Print()
//{
//    Node *p = root;
//    while(p -> next != NULL){
//        printf("->%d %d ", p ->type, p -> num);
//        p = p -> next;
//    }
//    printf("\n");
//}

//感觉不应该会错,而应该会超时什么的一类。
int main()
{
//    freopen("1.txt", "r", stdin);
    int n, k = 0;
    while(scanf("%d", &n) && n){
        memset(head, NULL, sizeof(head));//remember the first same type.
        memset(hash, 0, sizeof(hash));
        int m, x;
        for(int i = 1; i <= n; i ++){
            scanf("%d", &m);
            for(int j = 1; j <= m; j ++){
                scanf("%d", &x);
                hash[x] = i;
            }
        }
        printf("Scenario #%d\n", ++ k);
        root = new Node();// root node is empty;
        tail = new Node();
        root -> next = tail;
        char order[10];
        while(scanf("%s", order) && order[0] != 'S'){
            if(order[0] == 'E'){
                scanf("%d", &x);
                insert(hash[x], x);
            }
            else {
                if(root -> next != tail){// out the queue, may be the queue is empty... nop
                    printf("%d\n", root -> next -> num);
                    if(root -> next -> type == root -> next -> next -> type){
                        head[root -> next -> type] = root -> next -> next;
                    }
                    else head[root -> next -> type] = NULL;
                    root = root -> next;
                    root -> type = -1;
                }
            }
        }
        puts("");
        delete root; delete tail;
    }
    return 0;
}
</span>

网上的方法大多数用的是队列。

主队列记录队序,副队列来记录元素。是一种很方面的方法。这要求你对stl有很深的理解。

code:

<span style="font-size:18px;">#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
using namespace std;

const int N = 1e6 + 5;
const int M = 1e3 + 5;
int hash[N];
int main()
{
//    freopen("1.txt", "r", stdin);
    int t, k = 1;
    while(scanf("%d", &t) && t){
        memset(hash, 0, sizeof(hash));
        int n, x;
        for(int i = 1; i <= t; i ++){
            scanf("%d", &n);
            for(int j = 1; j <= n; j ++){
                scanf("%d", &x);
                hash[x] = i;
            }
        }
        printf("Scenario #%d\n", k ++);
        string ord;
        queue<int> mainp, p[M];
        // 主队里面放队序,副队里面放元素。
        while(cin >> ord && ord != "STOP"){
            if(ord == "ENQUEUE"){
                cin >> x;
                if(p[hash[x]].empty()) mainp.push(hash[x]);
                p[hash[x]].push(x);
            }
            else {
                cout << p[mainp.front()].front() << endl;
                p[mainp.front()].pop();
                if(p[mainp.front()].empty()){
                    mainp.pop();
                }
            }
        }
        cout << endl;
    }
    return 0;
}
</span>

很好的一道题目。。。。

很高兴,现在发现了bug。。嘎嘎。

看到还有用数组模拟队列实现的,表示很好很强大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于HDU4546问题,还可以使用优先队列(Priority Queue)来解决。以下是使用优先队列的解法思路: 1. 首先,将数组a进行排序,以便后续处理。 2. 创建一个优先队列(最小堆),用于存储组合之和的候选值。 3. 初始化优先队列,将初始情况(即前0个数的组合之和)加入队列。 4. 开始从1到n遍历数组a的元素,对于每个元素a[i],将当前队列中的所有候选值取出,分别加上a[i],然后再将加和的结果作为新的候选值加入队列。 5. 重复步骤4直到遍历完所有元素。 6. 当队列的大小超过k时,将队列中的最小值弹出。 7. 最后,队列中的所有候选值之和即为前k小的组合之和。 以下是使用优先队列解决HDU4546问题的代码示例: ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); // 对数组a进行排序 priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆 pq.push(0); // 初始情况,前0个数的组合之和为0 for (int i = 0; i < n; i++) { long long num = pq.top(); // 取出当前队列中的最小值 pq.pop(); for (int j = i + 1; j <= n; j++) { pq.push(num + a[i]); // 将所有加和结果作为新的候选值加入队列 num += a[i]; } if (pq.size() > k) { pq.pop(); // 当队列大小超过k时,弹出最小值 } } long long sum = 0; while (!pq.empty()) { sum += pq.top(); // 求队列中所有候选值之和 pq.pop(); } cout << sum << endl; return 0; } ``` 使用优先队列的方法可以有效地找到前k小的组合之和,时间复杂度为O(nklog(k))。希望这个解法对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值