HDU 2295(裸DLX要超时,需要剪枝)

本文介绍了一种基于回溯算法的雷达覆盖优化方案。通过构建图模型来解决雷达站点如何覆盖尽可能多的城市节点的问题,并利用算法X求解精确覆盖问题。算法通过不断调整雷达的有效覆盖范围,寻找最优解。

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

 

多了Judge()要是depth+judge()都大于count就直接返回false;

 

#include <iostream>

#include <cmath>

#include <stdio.h>

using namespace std;

 

const int N=100;

struct node{

int L,R,D,U,col;

}dia[N*N];

double map[N][N];

int Size[N];

 

pair<double,double>city[N],Radar[N];

 

int n,m,count;

void makegraph(double mid)

{

int i,j,now,pre,RP;

//////初始化头指针///////////

for(i=0;i<=n;i++)

{

dia[i].col=i;

dia[i].D=dia[i].U=i;

dia[i].L=i-1;

dia[i].R=i+1;

Size[i] = 0;

}

dia[0].L=n;dia[n].R=0;

now=n+1;

for(i=1;i<=m;i++)

{

RP=pre=now;//RP行指针

for(j=1;j<=n;j++)

if(map[i][j]<mid){

dia[now].col = j;//属于第几列

Size[j] ++;

 

dia[now].U = dia[j].U;

dia[now].D = j;

dia[dia[j].U].D = now;

dia[j].U = now;

 

dia[now].L=pre;

dia[now].R=RP;

dia[pre].R = now;

dia[RP].L = now;

pre = now++;

}

}

}

 

void Cover(int c)

{

//dia[dia[c].R].L = dia[c].L;

//dia[dia[c].L].R = dia[c].R;

for(int i=dia[c].D;i!=c;i=dia[i].D)

{

dia[dia[i].L].R = dia[i].R;

dia[dia[i].R].L = dia[i].L;

Size[dia[i].col] --;

}

}

void Recover(int c)

{

for(int i=dia[c].U;i!= c;i=dia[i].U)

//for(int j=dia[i].L;j!=i;j=dia[j].L)

{

dia[dia[i].L].R = i;

dia[dia[i].R].L = i;

Size[dia[i].col] ++;

}

//dia[dia[c].R].L=c;

//dia[dia[c].L].R=c;

}

 

int judge()

{

    int hash[N]={0};

    int ans=0,i,j,k;

    for(i=dia[0].R;i;i=dia[i].R)

        if(!hash[i])

        {

            ans++;

            hash[i]=1;

            for(j=dia[i].D;j!=i;j=dia[j].D)

                for(k=dia[j].R;k!=j;k=dia[k].R)

                    hash[dia[k].col]=1;

        }

    return ans;

}

bool Algorithm_X(int depth)

{

int i,j;

if(depth+judge()>count) 

//if(depth>count)

return false;

if(dia[0].R == 0)

return true;

 

int mi=0xfffffff,c_pos;

for(i=dia[0].R;i!=0;i=dia[i].R)

if(mi>Size[i]){

mi = Size[i];

c_pos = i;

if(mi == 1) break;

}

//if(Size[c_pos] == 0) return false;

//Cover(c_pos);

for(i=dia[c_pos].D;i != c_pos; i=dia[i].D)

{

Cover(i);

for(j=dia[i].R;j != i; j=dia[j].R)

Cover(j);

if(Algorithm_X(depth+1))

return true;

for(j=dia[i].L;j!=i;j=dia[j].L)

Recover(j);

Recover(i);

}

//Recover(c_pos);

return false;

}

 

void Init(double &ma)

{

int i,j;

for(i=1;i<=m;i++)

for(j=1;j<=n;j++)

{

map[i][j] = sqrt( (city[j].first-Radar[i].first) *(city[j].first-Radar[i].first)

+ (city[j].second - Radar[i].second) *(city[j].second - Radar[i].second) );

ma = max(ma,map[i][j]);

}

}

 

void print(double mid)

{

for(int i=1;i<=n;i++)

{

for(int j=1;j<=m;j++)

if(map[i][j]<=mid)

{

printf("1 ");

}

else

printf("0 ");

printf("/n");

}

}

 

int main()

{

int i,j;

int T;

scanf("%d",&T);

while(T --)

{

// memset(Size,0,sizeof(Size)

scanf("%d%d%d",&n,&m,&count);

for(i=1;i<=n;i++)

scanf("%lf%lf",&city[i].first,&city[i].second);

for(i=1;i<=m;i++)

scanf("%lf%lf",&Radar[i].first,&Radar[i].second);

double ma=0;

Init(ma);

double low=0,high=ma+1,mid;

while(low+1e-8<=high)

{

mid = (low+high)/2;

//mid = 3;

// printf("mid = %lf/n",mid);

makegraph(mid);

// print(mid);

bool flag = true;

/*for(i=dia[0].R;i!=0;i=dia[i].R)

if(Size[i]==0){

flag = false;

break;

}*/

if(flag && Algorithm_X(0))

high=mid;

else

low = mid;

}

printf("%.6lf/n",low);

}

return 0;

}

<think>嗯,用户想解决HDU1873的“看病要排队”问题。首先我得回忆一下题目要求。题目大意是说有三个医生,病人根据优先级被分配到不同的医生队列中,每次处理优先级最高的病人,如果优先级相同则先到先得。输出每次OUT操作时的病人ID或者EMPTY。 根据用户提供的引用,比如引用3和5,他们提到了使用优先队列(priority_queue)来模拟医生的队列。优先队列能自动按照优先级排序,这应该是个关键点。结构体需要包含优先级和病人ID,并且要自定义比较函数,使得队列首先按优先级降序排列,相同优先级时按ID升序,也就是先来的先处理。 用户引用的代码中有不同的实现方式,比如引用3使用了结构体运算符重载,而引用5则定义了比较函数。这时候需要比较这两种方法的异同,并选择更清晰的方式解释给用户。例如,运算符重载在C++中更符合优先队列的默认行为,可能更容易实现。 另外,引用4提到用结构体数组和排序,虽然可行但效率可能不如优先队列,因为每次插入都要重新排序,时间复杂度较高。而优先队列的插入和取出操作都是O(log n),更适合这种场景。 接下来要考虑如何组织代码结构。主函数需要处理多个测试用例,每个用例中处理IN和OUT操作。IN操作时,将病人加入对应医生的队列;OUT操作时,取出队首元素或输出EMPTY。 需要注意的细节包括:病人ID是按IN操作的顺序递增的,所以需要维护一个全局计数器。每个医生对应一个优先队列,这里可以用数组来存储三个优先队列。 代码示例部分需要正确展示结构体的定义和优先队列的使用。比如,结构体中的operator<如何定义,优先队列的声明方式,以及如何处理输入输出。 可能的问题点:优先队列默认是大顶堆,所以在定义比较运算符时要确保优先级高的排在前面。比如,当比较a和b时,如果a的优先级更高,应该返回true吗?或者需要调整符号?比如在引用3中,运算符重载里比较的是A.rank > rank,这可能涉及到优先队列的排序逻辑,需要仔细检查是否正确。 测试用例的处理也很重要,例如输入可能有多个测试案例,需要用循环读取直到输入结束。这在C++中通常用while(cin >> num)之类的结构处理。 最后,生成相关问题时要围绕解题方法、优化、数据结构选择等,比如比较优先队列与其他方法的优劣,如何处理相同优先级的情况,或者如何扩展到更多医生的情况。</think>### HDU1873 看病要排队 解题思路 #### 核心问题分析 题目要求模拟医院三个医生的就诊队列,满足以下条件: 1. **优先权排序**:优先诊治病情等级(10级最高,1级最低)高的患者 2. **时间顺序**:相同优先级时,按患者到达顺序(ID递增)处理 3. **动态操作**:支持两种指令: - `IN A B`:将优先级为$B$的患者加入医生$A$的队列 - `OUT A`:从医生$A$的队列中取出最高优先级患者并输出其ID #### 数据结构选择 - **优先队列(堆)**:天然支持按自定义规则排序,插入/删除时间复杂度为$O(\log n)$[^3][^5] - **结构体定义**:需包含`优先级`和`患者ID`两个字段 ```cpp struct Patient { int priority; int id; bool operator<(const Patient &other) const { if (priority == other.priority) return id > other.id; // 小ID优先 return priority < other.priority; // 高优先级优先 } }; ``` #### 算法实现步骤 1. **初始化**:创建3个优先队列对应医生1-3 2. **指令处理**: - `IN`指令:将患者加入对应队列 - `OUT`指令:若队列非空则输出并弹出队首元素 3. **排序规则**:通过重载运算符实现双条件排序 --- ### HDU1873 代码实现 ```cpp #include <iostream> #include <queue> using namespace std; struct Patient { int prio, id; bool operator<(const Patient &o) const { return (prio != o.prio) ? (prio < o.prio) : (id > o.id); } }; int main() { int n; while (cin >> n) { priority_queue<Patient> doctors[4]; // 下标1-3对应医生 int cnt = 0; // 全局ID计数器 while (n--) { string op; cin >> op; if (op == "IN") { int a, b; cin >> a >> b; doctors[a].push({b, ++cnt}); } else { int a; cin >> a; if (doctors[a].empty()) { cout << "EMPTY" << endl; } else { cout << doctors[a].top().id << endl; doctors[a].pop(); } } } } return 0; } ``` #### 关键点说明 1. **运算符重载**:`prio < o.prio`确保高优先级先出队,`id > o.id`确保同优先级时早到的先处理[^3][^5] 2. **队列索引**:使用`doctors[4]`使得医生编号直接作为数组下标 3. **ID生成**:通过`++cnt`保证患者ID全局唯一且递增 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值