hdu1276士兵队列问题

这题看题意就有队列的意思,可以开始队列掌握的太差,稍加改变,没看出来怎么应用队列。
当然没用队列的思想也可以用数组模拟这个过程
代码奉上

#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int a[5001];
int main()
{
    std::ios::sync_with_stdio(false);//减少cin读入的时间
    int T;
    cin>>T;
    memset(a,0,sizeof(a));
    while(T--)
    {
        int n;
        cin>>n;
        int sum=n;
        for(int i=1;i<=n;i++)
            a[i]=i;
        if(n<=3)
        {
            cout << "1";
            for(int i = 2; i<=n; i++)
            {
                if(a[i])
                {
                   cout << " " << a[i];
                }
            }
            cout<<endl;
            continue;
        }
        while(1)
        {
            int flag=0;
            for(int i=1;i<=n;i++)
            {
                if(a[i])
                {
                    flag++;
                }
                if(flag==2)
                {
                    a[i]=0;
                    flag=0;
                    sum--;
                }
            }
            if(sum<=3)
                break;
                flag=0;
            for(int i=1;i<=n;i++)
            {
                if(a[i])
                {
                    flag++;
                }
                if(flag==3)
                {
                    a[i]=0;
                    flag=0;
                    sum--;
                }
            }
            if(sum<=3)
                break;
        }
        cout<<"1";
        sum--;
        for(int i=2;sum;i++)
        {
            if(a[i])
            {
                cout<<" "<<a[i];
                sum--;
            }
        }
      cout<<endl;
    }
    return 0;
}

后来看了别人用到队列写这道题,感觉想法很不错,数到要出列就让它出列,不该出列的就放在队尾,并且在每个队尾加个0,控制 遍历一次,结束的条件。详细见代码

#include <iostream>  
#include <queue>  
using namespace std;  
queue<int> s;  
void cmp(int k)  
{  
 int i=1;  
 while(s.front()!=0)  
 {   
  if(i%k!=0) //把留下来的方队尾  
   s.push(s.front());  
  s.pop();i++; //去掉队首  
 }s.pop();s.push(0); //把队首的0去掉,在队尾加上0  
}  
int main (void)  
{  
 int t,n,i,j,k,l;  
 cin>>t;  
 while(t--&&cin>>n)  
 {  
  for(i=1;i<=n;i++)  
   s.push(i);s.push(0); //每次在屁股加上个0  
  i=1;  
  while(s.size()>4) //因为加上了0,所以长度小于等于4就退出  
  {  
   if(i%2==0)cmp(3); //选择数三下踢一个人还是数两下踢一个人  
   else cmp(2);  
   i++;  
  }i=0;  
  while(!s.empty()) //查看队列中是不是为空  
  {  
   if(s.front()>0) //因为队尾还有个0,这个是不用输出的但是为了清空队列,还是要pop他  
   {  
    if(i)cout<<" ";i=1;  
    cout<<s.front();  
   }  
   s.pop();  
  }cout<<endl;  
 }  
 return 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、付费专栏及课程。

余额充值