自出题,写题解《招募士兵》

本文介绍了一个关于军队招募的成本优化问题。小W希望通过利用候选人之间的关系来降低招募士兵的总成本。通过使用并查集算法对关系进行排序,并判断是否可以合并以减少费用,最终求得最小总花费。

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

招募士兵
(conscription.pas/c/cpp)
【问题描述】
小W拥有一个国家,现在他希望建立一支军队来保护他的国家。他选中了N个女孩和M个男孩希望招募他们成为他的士兵。在没有任何先决条件的情况下,他招募一个士兵需要花费10000RMB。现在小W可以利用这些人之间的关系来减少他的花费。如果女孩X和男孩Y存在有一个关系值D(两人之间可能有多个关系值),而且她们之中有一个人被招募了。那么小W可以在招募另一个人的时候减少D的花费(实际10000-D的费用)。
现在给你这些男孩女孩之间的关系,希望你告诉小W告诉他招募所有人的最少花费。
注意:招募某一个人时,只能利用一个关系。
【输入】
输入文件conscription.in中文件第一行包含三个整数N,M,R。表示N个女孩,M个男孩与R条关系。
接下来R行,每行包含三个整数Xi,Yi和Di,表示女孩Xi和男孩Yi有Di的关系。
【输出】
conscription.out中只有一行一个数,为最小费用。
【输出样例】
5 5 8
4 3 6831
1 3 4583
0 0 6592
0 1 3063
3 3 4975
1 3 2049
4 2 2104
2 2 781
【输出样例】
71071

【数据说明】
100%的数据:1<=N, M <=100000,0 <=R <=200,000,0 < di < 10000

本题烤驴到一个并查集的问题,然后,我们把他可以减少的价钱排个序,再一个一个地去并起来,如果他们的father一样,就不可以并起来,这样子就能解决问题。

参考程序:

type
        new=record
                x:longint;
                y:longint;
                r:longint;
                bz:boolean;
        end;

var
        i,j,k,l,n,m,r,v,x,y:longint;
        ans:int64;
        f:array[0..200000] of longint;
        a:array[1..200000] of new;
        bz:boolean;
procedure qs(l,r:longint);
var
        i,j,m:longint;
        t:new;
begin
        i:=l;
        j:=r;
        m:=a[(l+r) div 2].r;
        repeat
                while a[i].r>m do inc(i);
                while a[j].r<m do dec(j);
                if i<=j then
                begin
                        t:=a[i];
                        a[i]:=a[j];
                        a[j]:=t;
                        inc(i);
                        dec(j);
                end;
        until i>j;
        if l<j then qs(l,j);
        if i<r then qs(i,r);
end;
function zs(t:longint):longint;
var
        i,j,k,l:longint;
begin
        l:=t;
        while f[t]<>t do
        begin
                t:=f[t];
        end;
        while f[l]<>t do
        begin
                j:=f[l];
                f[l]:=t;
                l:=j;
        end;
        zs:=t;

end;

begin
        readln(n,m,r);
        for i:=1 to r do
        begin
                readln(a[i].x,a[i].y,a[i].r);
                a[i].y:=a[i].y+n;
        end;
        for i:=1 to n+m do f[i]:=i;
        qs(1,r);
        ans:=0;
        v:=0;

        for i:=1 to r do
        begin
                if zs(a[i].x)<>zs(a[i].y) then
                begin
                        x:=zs(a[i].x);
                        y:=zs(a[i].y);
                        f[x]:=y;
                        a[i].bz:=true;
                        ans:=ans+(10000-a[i].r);
                        inc(v);
                end;
        end;
        writeln(ans+(n+m-v)*10000);
end.

<think>好的,我现在需要帮用户根据他们的代码题解。用户提供的代码是关于用泰勒级数展开计算π的值,使用了arctan函数的展开式,并且通过6倍的arctan(1/√3)来计算π。用户要求题解不要改动他们的代码,内容要丰富,参考他们提供的模板。 首先,我需要理解用户的代码结构。代码中定义了一个函数xx,用来计算arctan(x)的近似值,使用的是泰勒级数展开,直到某一项小于1e-6时停止。主函数中调用这个函数,并乘以6得到π的值,保留小数点后10位。 接下来,我需要按照用户提供的模板来组织题解。模板包括题目、思路(暴搜、代码、时间复杂度等部分),但用户的题目是关于数值计算的,可能需要调整结构。用户提供的示例是关于质数分解的,但当前问题属于数值方法,所以需要转换思路。 题目部分应该明确题目要求,即根据给定的泰勒级数展开式,编函数计算π的值,当最后一项小于1e-6时停止。然后,思路部分需要解释所使用的数学公式和算法。 用户的代码中,函数xx实现了泰勒级数的累加,每次循环累加一项,直到下一项小于1e-6为止。这里需要注意终止条件是否正确,因为用户代码中的判断是if ((pow(x, i)/i) <= 1e-6),但泰勒级数是交替级数,所以最后一项的绝对值需要小于1e-6才能保证总和的误差不超过该值。可能用户的代码中的条件是否存在问题?比如,是否应该检查当前项的绝对值是否小于1e-6,而不是直接比较。但用户要求不修改代码,所以题解中需要解释现有代码的逻辑。 在思路部分,可以分为数学推导和算法实现。数学推导部分解释为什么使用arctan(1/√3)乘以6等于π。可能需要提到tan(π/6)=1/√3,因此arctan(1/√3)=π/6,所以π=6*arctan(1/√3)。这部分对理解题目很重要。 算法实现部分需要解释代码中的循环结构,如何累加级数项,交替改变符号,以及终止条件。同时,指出需要注意的地方,比如浮点数精度问题,循环终止条件的正确性,以及输出格式保留10位小数。 代码部分需要展示用户的代码,并解释关键部分。比如,在xx函数中,变量v保存累加结果,i从1开始,每次加2,对应泰勒级数的x^3/3、x^5/5等项。id用于交替符号。循环中计算当前项的值,并判断下一项是否小于等于1e-6作为终止条件。这里可能存在的疑问是,是否应该检查当前项是否小于1e-6,而用户的代码是检查下一项,这可能导致多计算一项。但用户要求不修改代码,所以题解中需要如实描述。 时间复杂度可能不太适用,但可以讨论迭代次数,比如当x=1/√3时,每一项的大小递减,直到满足终止条件,所以循环次数是有限的,收敛速度如何。 相关问题部分需要根据用户提供的示例格式,生成3-5个相关问题,如优化计算效率、修改终止条件、选择该公式的原因、验证精度、递归实现的可行性等。 最后,确保整个题解结构清晰,符合用户提供的模板风格,使用适当的Markdown格式,避免使用代码块以外的格式错误。同时,检查是否所有内容都符合用户的要求,没有改动代码,并解释了代码的各个部分。</think>题目 - 基于泰勒级数展开式计算π的值 要求使用公式:arctan(x)=x−x³/3+x⁵/5−x⁷/7+... 且 π=6arctan(1/√3) 当级数最后一项的绝对值小于10⁻⁶时停止计算 思路 - ### 数学推导 1. **公式选择依据** 根据三角恒等式 tan(π/6)=1/√3,得 arctan(1/√3)=π/6 因此 π=6arctan(1/√3),该公式收敛速度较快 2. **级数特性** 该级数为交错级数(正负交替),每一项绝对值单调递减 当终止项|xⁿ/n|<1e-6时,总和误差将小于1e-6 ### 算法实现 1. **级数计算** - 使用变量`v`累加各项 - `i`从1开始递增2,对应指数和分母 - `id`控制符号交替(+1/-1) - 终止条件:下一项|xⁿ/n| ≤ 1e-6时返回结果 2. **精度控制** - 采用double类型保证15位有效数字 - 最终结果保留小数点后10位 ### 代码解析 ```cpp double xx(double x){ double v=0; int i=1,id=1; while(1){ v += id * pow(x,i)/i; // 累加当前项 i += 2; // 指数递增 if(pow(x,i)/i <= 1e-6) return v; // 终止条件 id *= -1; // 符号交替 } } ``` 主函数中: ```cpp pi = 6.0 * xx(1.0/sqrt(3)); // 应用π公式 cout << fixed << setprecision(10) << pi; // 格式化输出 ``` ### 收敛性分析 当x=1/√3≈0.577时,级数项|xⁿ/n|随n指数衰减: - 第1项:0.577/1 ≈0.577 - 第3项:0.192/3 ≈0.064 - 第5项:0.064/5 ≈0.0128 - 第15项:0.0007/15≈4.7e-5 - 约需计算到i=21时满足终止条件
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值