挖宝

本文介绍了一种解决挖宝问题的方法,利用二分答案与动态规划技术,将复杂的分数最大化问题转化为整数操作问题。通过枚举答案A,并验证其可行性,逐步逼近最优解。

挖宝(二分答案+dp)

n个点,有m条边连接。小R从第一个点开始走,且必须从编号小的点走到编号大的点,直到走到第n个点。 每条边有时间\(t[i]\),价值\(w[i]\),求\(max(\frac{\sum w[i]}{\sum t[i]})\)

先考虑直接dp出答案,怎么设计状态呢?我们发现分数是不能累加的,导致转移不了状态。所以可不可以通过枚举答案,然后验证解来解题呢?如果当前枚举的答案是A,说明\(\sum w[i]-\sum t[i]*A=0\)。于是这样,我们就把分数的状态转化成了整数,可以进行累加了。\(f[i]\)表示前i个点,\(\sum w[i]-\sum t[i]*A\)的最大值。k是i的后继点,那么\(f[k]=max(f[i]+w[k, i]-t[k, i]*A, f[k])\)。如果\(f[k]>0\),说明答案比A大,否则说明答案比A小。于是二分答案即可。

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=1e4+5, maxm=1e5+5, INF=1e9;
const double eps=1e-5;

class Graph{
public:
    struct Edge{
        int to, next, t, w; Graph *bel;
        Edge& operator ++(){ return *this=bel->edge[next]; }
        inline int operator *(){ return to; }
    };
    void addedge(int x, int y, int t, int w){
        Edge &e=edge[++cntedge]; e.bel=this;
        e.to=y; e.next=fir[x]; e.t=t; e.w=w;
        fir[x]=cntedge;
    }
    Edge& getlink(int x){ return edge[fir[x]]; }
private:
    int cntedge, fir[maxn];
    Edge edge[maxm*2];
};

Graph g;
int n, m;
double f[maxn];

bool ok(double A){
    fill(f, f+maxn, -INF);
    f[1]=0; Graph::Edge e;
    for (int i=1; i<=n; ++i){
        e=g.getlink(i);
        for (; *e; ++e){
            if (*e<i) continue;
            f[*e]=max(f[*e], f[i]+e.w-e.t*A);
        }
    }
    return f[n]>0;
}

int main(){
    scanf("%d%d", &n, &m);
    int a, b, c, d; double l=0, r=1e5, mid;
    for (int i=0; i<m; ++i){
        scanf("%d%d%d%d", &a, &b, &c, &d);
        if (a>b) swap(a, b);
        g.addedge(a, b, c, d);
    }
    while (r-l>eps){
        mid=(r+l)/2;
        if (ok(mid)) l=mid; else r=mid;
    }
    printf("%.4lf", mid);
    return 0;
}

转载于:https://www.cnblogs.com/MyNameIsPc/p/7770531.html

### 关于蓝桥杯Scratch组“矿工”真题及解法 #### 题目背景与要求 蓝桥杯Scratch组的“矿工”是一道典型的编程题目,主要考察学生的逻辑思维能力和对Scratch基本功能的应用能力。根据已知的信息[^5],“矿工”的核心需求如下: - 场景设定:舞台上存在地底区域,作为矿工活动的空间。 - 物生成规则:2个金块和2个钻石会随机出现在地底下,但需满足不接触舞台边缘的要求。 - 动态交互:玩家通过控制角色(矿工),收集这些随机分布的物。 --- #### 技术要点分析 ##### 1. **随机位置设置** 为了使金块和钻石随机分布在地底区域内而不超出边界,可以通过调整`x坐标`和`y坐标`的取值范围来实现。具体做法是定义一个合理的随机数区间,例如: ```scratch 当绿旗被点击 将 [x 坐标 v] 设为 (pick random (-100) to (100)) 将 [y 坐标 v] 设为 (pick random (-180) to (-80)) // 确保 y 值位于地底范围内 ``` 上述代码片段中的`(-180)`到`(-80)`代表了地底的具体高度范围,可以根据实际场景进一步微调。 ##### 2. **碰撞检测机制** 在Scratch中,判断矿工是否成功采集到某个物通常依赖于**碰到某对象时触发事件**的功能。以下是可能的实现方式: ```scratch 如果 <触碰 [金块 v]> 那么 隐藏 [金块 v] 增加得分 播放音效... 结束 ``` 此部分需要分别针对每种类型的物编写对应的脚本,并确保每次拾取后更新界面状态或分数显示。 ##### 3. **避免重复生成相同物品** 为了避免多个物重叠在同一地点,可以在创建新实例之前先检查目标位置附近是否有其他物体存在。利用广播消息或者变量标记的方法可以帮助解决这一问题[^3]。 --- #### 示例程序结构设计 下面给出一段简化版的整体框架供参考: ```scratch // 初始化阶段 当绿旗被点击 清除屏幕 绘制地面线条或其他装饰元素 克隆两个 “金块” 和两个 “钻石” // 单独处理每个克隆体的行为模式 当作为克隆体启动时 移动至指定初始点位 等待直到被捡起才消失 // 用户操作响应模块 永远执行循环 { 如果按下方向键,则改变当前角色朝向并前进几步; } ``` 以上仅为概念性的描述,请结合实际情况灵活调整细节参数配置。 --- #### 学习资源推荐 对于希望深入理解此类竞赛题目的选手来说,可以从以下几个方面入手准备[^4]: - 参加官方提供的免费在线培训课程,熟悉最新版本软件的各项特性。 - 查阅往期类似主题的经典案例解析文档,积累实战经验。 - 加入相关兴趣小组讨论群聊,与其他爱好者共同探讨疑难杂症解决方案。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值