D1&D2

Day1
T1分绳子
题意:有一根长度为 l 的绳子,需要把这根绳子剪成两段,一段围成圆形,一段围成正方形,问怎样分割可以使两个图形的总面积最小,总面积最小为多少?(要求精度为小数点后三位)
Input
一行一个整数 l
Output
一行一个为总面积 S,保留六位小数
Hint
20% l<=100
70% l<=1e6
100% l<=1e7
思路:设正方形的周长为x,则圆形分得的周长为(l - x),可得正方形边长为x / 4,圆形半径为(l - x) / 2pi,则正方形面积为x2 / 16,圆形面积为
pi(l - x)2 / 4pi2=(l - x)2/4pi,所以总面积S=x2/16+(l - x)2 / 4pi=(pix2+4(l-x)2)/16pi=((4+pi)x2-4Lx+4L2)/16pi,可知当x=-b/2a=-4L/2(4+pi)=-2L/(4+pi)时,S最小为L2/(16+4pi)
代码:

#include<stdio.h>
using namespace std;
double I;
const double pi = 3.14159265358979;
int main(){
    scanf("%lf",&I);
    printf("%.6lf",I * I / (16 + 4 * pi));
    return 0;
}
//没想到这道题这么短吧

Day2:
T1:买牛奶
题意:因为牛奶包装产生的利润很低,所以要将原材料的价格控制的尽可能低。Miller 公司有几个农民,每天可以从农民那里购买一定数量的牛奶,这个数量要少于等于农民的限额。给定 Miller 公司每天的牛奶需求,以及每个农民有的牛奶的数量和每升牛奶的价格,计算满足 Miller 公司牛奶需求所需要的最低金额(需求一定可以被满足)
Input
第一行两个整数𝑛和𝑚,分别表示 Miller 公司今天的牛奶需求𝑛和农民的人数𝑚。
接下来 m 行,每行包含两个整数,𝑝𝑖和𝑎𝑖,分别表示农民𝑖收取的牛奶价格和农
民𝑖今天可以卖给 miller 公司的牛奶的数量。
Output
一行一个整数,是 Miller 公司今天能买到牛奶的最低价格。
Hint:
20% 0 ≤ 𝑁 ≤ 100, 0 ≤ 𝑀 ≤ 20
100% 0 ≤ 𝑁 ≤ 2,000,000,0 ≤ 𝑀 ≤ 5,000,0 ≤ 𝑃𝑖 ≤ 1,000,0 ≤ 𝐴𝑖 ≤ 5,000
思路:
由于牛奶是液体,可以分开买,所以不是01背包,是贪心。先按照价格从小到大排序,然后从小到大购买牛奶直到足够需求
代码:

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxm = 5010;
long long n;
int m;
struct node{
    long long price,a;
}a[maxm];
struct cmp{
    bool operator ()(node x,node y){
        return x.price < y.price;
    }
};
int main(){
    scanf("%lld%d",&n,&m);
    for(int i = 1;i <= m;i++){
        scanf("%lld%lld",&a[i].price,&a[i].a);
    }
    sort(a + 1,a + 1 + m,cmp());
    long long ans = 0;
    for(int i = 1;i <= m;i++){
        if(n <= 0)break;
        if(n - a[i].a >= 0){
            n -= a[i].a;
            ans += a[i].price * a[i].a;
        }
        else{
            ans += a[i].price * n;
            n = 0;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

T2:电梯
题意:小 Y 现在正在电视塔下一个停在竖直轨道最下面的电梯面前,他希望通过这
部电梯来到塔顶。这个电梯的升降是由一个手柄控制的。电视塔一共 N 层,电梯
可以停在每一层,手柄有 M 个控制槽,第 i 个控制槽旁边标着一个数𝑐𝑖。如果
𝑐𝑖 > 0,表示手柄扳到该槽电梯将上升𝑐𝑖层;如果𝑐𝑖 < 0,表示手柄扳动到该槽将
下降𝑐𝑖层。并且一定存在一个𝑐𝑖 = 0的槽,手柄最初就在这个槽中。注意,电梯只
能在 1~N 层移动。
电梯每移动一层,需要花费 2s 的时间,而将手柄从一个槽板到相邻的槽需
要花费 1s 的时间。现在小 Y 在 1 层,他想知道最快需要多长时间可以到 N 层。
Input
第一行两个整数 N、M,分别为电视塔层数和手柄控制槽个数。
第二行 M 个整数,𝑐1, 𝑐2, … , 𝑐𝑀
Output
一行一个整数,表示最少需要多长时间可以到塔顶。若不可能到达则输出-1。
Hint
30% 1 ≤ 𝑁 ≤ 10, 2 ≤ 𝑀 ≤ 5
100% 1 ≤ 𝑁 ≤ 100, 2 ≤ 𝑀 ≤ 20, −𝑁 < 𝑐1 < 𝑐2 < ⋯ < 𝑐𝑀 < 𝑁
思路:
由于数据较小,所以直接暴力搜索+记忆化,考虑bfs()
先建立一个queue,每个点包括两个状态:所在层数lvl和手柄槽位c
并定义一个记忆数组book[i][j],i表示层数,j表示槽位,初始化定义为0x3f3f3f3f,并将book[1][初始槽位] = 0
接下来对于每一个点,考虑扩展方式,枚举每一个槽位(需要特判初始槽位,因为初始槽位是0,可能引发死循环),判断不会越界后将book[][]与现方案进行比较,如果现方案更快更新记忆数组,并加入队列(注:这里用到了SPFA的优化思想)
队列空后取book[n]中最小的方案,如果都为0x3f3f3f3f输出-1
代码:

#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<string.h>
#include<math.h>
using namespace std;
int n, m;
int temp = 0;
struct node{
    int lvl;
    int c;
}tmp,t;
queue<node> que;
int c[22];
int book[110][22];
int bfs(){
    tmp.lvl = 1;
    que.push(tmp);
    while(!que.empty()){
        tmp = que.front();
        que.pop();
        for(int i = 1;i <= m;i++){
            if(c[i] == 0 || tmp.lvl + c[i] < 1 || tmp.lvl + c[i] > n)continue;
            if(book[tmp.lvl + c[i]][i] > book[tmp.lvl][tmp.c] + abs(tmp.c - i) + abs(c[i]) * 2){
                book[tmp.lvl + c[i]][i] = book[tmp.lvl][tmp.c] + abs(tmp.c - i) + abs(c[i]) * 2;
                t.c = i;
                t.lvl = tmp.lvl + c[i];
                que.push(t);
            }
        }
    }
    int res = book[n][1];
    for(int i = 2;i <= m;i++){
        res = min(res,book[n][i]);
    }
    if(res == book[1][0]){
        return -1;
    }
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;i++){
        scanf("%d",&c[i]);
        if(c[i] == 0)temp = i;
    }
    memset(book,0x3f,sizeof(book));
    tmp.c = temp;
    book[1][temp] = 0;
    printf("%d\n",bfs());
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值