USACO 2.1.2 顺序的分数 Ordered Fractions

本文介绍了USACO中的2.1.2题,解决方法是枚举并排序所有分数。虽然尝试使用优先队列,但遇到STL priority_queue超时问题,后改为自定义堆实现,不过在调试过程中遇到错误,经过一番努力才解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题解

这道题其实很容易,枚举全部分数并且排序即可。
但是我用优先队列来做了,发现stl的priority_queue超时,然后自己手撸了个heap,
结果把下调写错了,debug了半天,尴尬-。- |||


代码

/*
PROG:frac1
ID:imking022
LANG:C++
 */
#include <iostream>
#include <cstdio>
#include <fstream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
int n,m,k;
typedef struct Node{
    int x,y;
    float dvd;
    Node(int a=0,int b=0):
        x(a),y(b) { dvd = (float)a/(float)b; }
}P;

P cot[16000];
bool vis[161][161];
int hod[100];
bool equ(Node &a,Node &b){
    if( abs(a.dvd - b.dvd) < 1e-5) return true;
    return false;
}

bool cmp2(Node &a,Node &b){
     if(equ(a,b)) return a.y > b.y;// spark!! 
     return a.dvd < b.dvd;
}
void flw(int pos){// 上浮
    if(pos<=1) return;
    while( pos!=1 && cmp2(cot[pos],cot[pos/2]) ){
        swap( cot[pos] , cot[pos/2] );
        pos/=2;
    }
}
void ins(P &p){// 入堆
    cot[k] = p;
    flw(k);
    k++;
}
P  del(){// 出堆
    if(k==1) return -1;
    P ret = cot[1];
    swap(cot[1],cot[k-1]);
    k--;

    int tar=1,pos=1;

    while( 2*pos<k ){// 向下调整!就是这里!
        tar = 2*pos;
        if(tar+1 < k){ // cmp2 :  <
            if(cmp2(cot[tar+1], cot[tar])) tar++; 
        }

        if(cmp2(cot[tar],cot[pos])){
            swap(cot[tar],cot[pos]);
            pos = tar;
        }else 
            break;
    }

    return ret;
}
int main(void){

    freopen("frac1.out","w",stdout);
    freopen("frac1.in","r",stdin);
    cin>>n;

    memset(vis,false,sizeof(vis));
    k=1;
    P tmp, p = Node(1,n);

    ins(p);
    vis[1][n] = true;
    cout<<"0/1\n";


    while(k>1){
        tmp = del();
        while(k>1 && equ(tmp,cot[1]) ){

            if( tmp.x+1 < tmp.y && !vis[tmp.x+1][tmp.y]){
                p =  Node(tmp.x+1,tmp.y );
                ins(p);
                vis[tmp.x+1][tmp.y] = true;
            }
            if(tmp.y-1 > tmp.x && !vis[tmp.x][tmp.y-1]){
                p = Node(tmp.x,tmp.y-1) ;
                ins(p);
                vis[tmp.x][tmp.y-1] = true;
            }
            tmp = del();
        }

        if(tmp.y%tmp.x == 0 )
            cout<<"1/"<<tmp.y/tmp.x<<endl;
        else
            cout<<tmp.x<<"/"<<tmp.y<<endl;

        if( tmp.x+1 < tmp.y && !vis[tmp.x+1][tmp.y]){
            p =  Node(tmp.x+1,tmp.y );
            ins(p);
            vis[tmp.x+1][tmp.y] = true;
        }
        if(tmp.y-1 > tmp.x && !vis[tmp.x][tmp.y-1]){
            p = Node(tmp.x,tmp.y-1) ;
            ins(p);
            vis[tmp.x][tmp.y-1] = true;
        }

    }

    if(n!=1) cout<<"1/1\n"; 

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值