当前位置: 首页 > news >正文

C语言应用实例:硕鼠游戏,田忌赛马,搬桌子,活动选择(贪心算法)

一、硕鼠游戏

1.题目

小老鼠准备了 M 磅的猫粮,准备去和看守仓库的猫做交易,因为仓库里有小老鼠喜欢吃的五香豆。

仓库有 N 个房间;
第 i 个房间有 J[i] 磅的五香豆,并且需要用 F[i] 磅的猫粮去交换;
老鼠不必交换该房间所有的五香豆,换句话说,它可以用 F[i]∗a% 磅的猫粮去换取 J[i]∗a% 磅的五香豆,其中 a 是一个实数。

现在,请帮忙计算一下,小老鼠最多能够得到多少磅的五香豆?

要求

输入包含多组测试用例。

每组测试数据首先一行是 2 个非负整数 M 和 N ,接着的 N 行,每行分别包含 2 个非负整数 J[i] 和 F[i] 。
输入数据以两个 −1 结束。
题目保证所有的数据不超过 1000

请计算并输出小老鼠最多能够得到的五香豆数量。
每组数据输出一行,保留 3 位小数。

2.题解

这是一个典型的贪心算法题

即不考虑全局,优先考虑局部最优解(全局是否最优需要证明)

代入题目即寻找能够获得最多猫粮的方案

有了思路,接下来便到了写代码的时候

读完要求我们会发现,每组数据有N个房间,每个房间至少包含两个数据(五香豆和猫粮),很明显,房间可以用一个结构体数组来表示,而数据则可以纳入对应结构体

结构体代码如下

struct mou{int beans;//存储房间内的豆子数量int mon;//存储需要缴纳的猫粮double mid;//计算单位数量的猫粮可兑换的豆子数量
};

核心算法如下

while(M){if(i<0){break;}if(M>=moulist[i].mon){sum+=moulist[i].beans;M-=moulist[i].mon;}else{sum+=moulist[i].mid*M;M=0;}i--;}

注:计算前先将结构体数组(moulist)按照mid大小排序

3.完整代码

#include<stdio.h>
#include<stdlib.h>struct mou{int beans;int mon;double mid;
};int compare(const void *a,const void *b){struct mou *m1 = (struct mou*)a;struct mou *m2 = (struct mou*)b;if(m1->mid > m2->mid) return 1;if(m1->mid < m2->mid) return -1;return 0;
}int main(){int M,N;while(1){scanf("%d %d",&M,&N);if(M==-1&&N==-1){break;}struct mou *moulist=(struct mou*)malloc(sizeof(struct mou)*N);for(int i=0;i<N;i++){struct mou m;scanf("%d %d",&m.beans,&m.mon);m.mid=(double)m.beans/m.mon;moulist[i]=m;}qsort(moulist,N,sizeof(struct mou),compare);double sum=0;int i=N-1;while(M){if(i<0){break;}if(M>=moulist[i].mon){sum+=moulist[i].beans;M-=moulist[i].mon;}else{sum+=moulist[i].mid*M;M=0;}i--;}printf("%.3lf\n", sum);free(moulist);}return 0;
}

二、田忌赛马

1.题目

“田忌赛马” 是中国历史上一个著名的故事。

大约2300年前,齐国大将田忌喜欢和国王赛马,并且约定:每赢一场,对方就要付 200 元。

假设已知田忌和国王的各自马匹的速度都不相同,请计算田忌最好的结果是什么。

要求:输入包含多组测试样例。

每组样例的第一行是一个整数 n(n<=1000),表示田忌和国王各自参赛的马匹数量。
接下来一行的 n 个整数表示田忌的马的速度,再接下来一行的 n个整数表示国王的马的速度。
n 为 0 时,表示输入数据的结束。

每组数据输出一行,表示田忌最多能够赢得的金额。

2.题解

这道题有两种情况:一种是田忌的马比国王的好,此时直接比就行;另一种是田忌的马比国王的差,此时则需要贪心算法

我们可以定义两个数组(t(田忌)和g(国王))用于存储马的质量

然后将二者分别排序便于后续操作

int compare(const void *a,const void *b){return (*(int*)a-*(int*)b);
}
int main(){
int t[n+1];int g[n+1];for(int i=0;i<n;i++){scanf("%d",&t[i]);}for(int i=0;i<n;i++){scanf("%d",&g[i]);}qsort(t,n,sizeof(int),compare);qsort(g,n,sizeof(int),compare);
}

核心算法如下

        int l=0;int r=n-1;int sum=0;for(int i=n-1;i>=0;i--){if(g[i]<t[r]){r--;sum++;}else if(g[i]>t[r]){l++;sum--;}}

3.完整代码

#include<stdio.h>
#include<stdlib.h>int compare(const void *a,const void *b){return (*(int*)a-*(int*)b);
}int main(){int n;while(1){scanf("%d",&n);if(n==0){break;}int t[n+1];int g[n+1];for(int i=0;i<n;i++){scanf("%d",&t[i]);}for(int i=0;i<n;i++){scanf("%d",&g[i]);}qsort(t,n,sizeof(int),compare);qsort(g,n,sizeof(int),compare);int l=0;int r=n-1;int sum=0;for(int i=n-1;i>=0;i--){if(g[i]<t[r]){r--;sum++;}else if(g[i]>t[r]){l++;sum--;}}printf("%d\n",sum*200);}return 0;
}

三、搬桌子

1.题目

已知楼层房间情况如下:

楼层中间是走廊,两侧各有 200 个房间,编号如图。

由于内部调整,需要把一些桌子从一个房间搬到另外的房间。
因为走廊很窄,但是桌子很大,所以同一段走廊每次只能通过一个桌子。

假设不论远近,每趟搬桌子都需要 10 分钟。
同时,当你从 房间i 搬桌子到 房间j 的过程中,房间i 到 房间j 之间的走廊都被占用,也就是说,在每个10分钟内,不能有多个任务共享同一段走廊。

现在,要完成所有的搬运任务,最少需要多少时间?

要求:输入包含 T 组测试用例。
每组测试用例首先是一个正整数 N(1<=N<=200),表示需要搬运的桌子数量。
接下来 N 行,每行包含 2 个正整数 s 和 t,表示需要将一个桌子从 房间s 搬到 房间t。

计算并输出完成所有的搬运任务需要的最少的时间,每组数据占一行。

2.题解

由题可知,中间一段走廊可以分为200段

那么如何找出总搬运时间呢?

其实很简单,我们只需用一个大小为201的数组来表示走廊,并初始化为0,然后每搬运一次就让其加一,最后找出最大重叠数乘10即可

(注意避开活动选择思想误区:即优先选择最早结束且满足要求的区间)

3.完整代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main(){int T;scanf("%d",&T);for(int i=0;i<T;i++){int N;scanf("%d",&N);int corridor[201] = {0}; // 走廊段,索引1-200for(int j=0;j<N;j++){int s, t;scanf("%d %d",&s,&t);// 确保s <= tif(s > t){int temp = s;s = t;t = temp;}// 将房间号映射到走廊段// 房间1-2 → 走廊段1,房间3-4 → 走廊段2,以此类推int start = (s + 1) / 2;int end = (t + 1) / 2;// 标记被占用的走廊段for(int k=start; k<=end; k++){corridor[k]++;}}// 找出最大重叠数int max_overlap = 0;for(int j=1; j<=200; j++){if(corridor[j] > max_overlap){max_overlap = corridor[j];}}printf("%d\n", max_overlap * 10);}return 0;
}

4.错误写法(活动选择思想)

这里再贴一下主包一开始的错误写法(还超时了)

(这并不贪心,而是另一种并排的思想)

#include<stdio.h>
#include<math.h>
#include<stdlib.h>struct Rom{int s,t;int num;
};int compare(const void *a,const void *b){struct Rom *m1 = (struct Rom*)a;struct Rom *m2 = (struct Rom*)b;if(m1->t > m2->t) return 1;if(m1->t < m2->t) return -1;return 0;
}int main(){int T;scanf("%d",&T);for(int i=0;i<T;i++){int N;scanf("%d",&N);struct Rom *romlist=(struct Rom*)malloc(sizeof(struct Rom)*N);for(int j=0;j<N;j++){struct Rom ro;scanf("%d %d",&ro.s,&ro.t);ro.num=1;romlist[j]=ro;}qsort(romlist,N,sizeof(struct Rom),compare);int a=N;int sum=0;int min=romlist[0].t;while(a){for(int j=0;j<N;j++){if(romlist[j].s>=min&&romlist[j].num!=0){sum++;romlist[j].num=0;a--;min=romlist[j].t;}}}printf("%d",sum*10);}return 0;
}

当笔记写了/doge

四、活动选择

1.题目

“今年暑假不AC?”
“是的。”
“那你干什么呢?”
“看世界杯呀,笨蛋!”
“@#$%^&*%…”

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。

作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)

要求输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Tis​,Tie​ (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。

对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。

2.题解

这是典型的活动选择题目

先定义节目结构体

struct Rom{int s,t;
};

然后定义节目结构体数组

struct Rom *romlist=(struct Rom*)malloc(sizeof(struct Rom)*N);

并将其按照结束时间排序

qsort(romlist,N,sizeof(struct Rom),compare);

贪心算法

int count = 1; // 至少可以选择第一个活动int last_end = romlist[0].t;for(int j=1;j<N;j++){if(romlist[j].s >= last_end){count++;last_end = romlist[j].t;}}

最后释放内存

3.完整代码

#include<stdio.h>
#include<stdlib.h>struct Rom{int s,t;
};int compare(const void *a,const void *b){struct Rom *m1 = (struct Rom*)a;struct Rom *m2 = (struct Rom*)b;if(m1->t > m2->t) return 1;if(m1->t < m2->t) return -1;return 0;
}int main(){int N;while(1){scanf("%d",&N);if(N==0){break;}struct Rom *romlist=(struct Rom*)malloc(sizeof(struct Rom)*N);for(int j=0;j<N;j++){scanf("%d %d",&romlist[j].s,&romlist[j].t);}qsort(romlist,N,sizeof(struct Rom),compare);int count = 1; int last_end = romlist[0].t;for(int j=1;j<N;j++){if(romlist[j].s >= last_end){count++;last_end = romlist[j].t;}}printf("%d\n",count);free(romlist);}return 0;
}

http://www.dtcms.com/a/582372.html

相关文章:

  • python+django/flask的医院财务管理系统
  • 网站开发常用框架电子商务网站建设的方法有哪些
  • 如何挑选出色的展厅机器人
  • 那种退不掉的网站怎么做的wordpress代码块
  • 锁机制详解:公平锁与非公平锁
  • 用vs2010做网站教程哪里网站建设便宜
  • 广州专业制作网站杭州网络优化公司排名
  • 建信建设投资有限公司网站网络营销品牌推广
  • asp 网站卡死多层次网络营销合法吗
  • 网站建设项目资金申请报告策划书的推广与运营
  • 网站开发可选择的方案学做立体书的网站
  • 网站建站流程网页设计制作页面
  • 基于SMPC随机模型预测控制的IEEE6电网系统matlab仿真,对比不允许负荷响应和允许负荷响应
  • 2025山西省网络安全职业技能大赛PWN方向题解
  • 郑州网站建设技术精粹一站式网站建设架构
  • 2025 年世界职业院校技能大赛机械设计与制造赛道备赛方案
  • 【2025软考高级架构师】——2024年11月架构真题解析
  • 基于HAL库实现看门狗喂狗实时时钟睡眠停止模式ADC采集w25qx写入读取
  • Linux系统编程——多线程编程(一)
  • 建设钓鱼网站源码网站seo优化心得
  • 关方网站买微信我们做网站 出教材 办育心经
  • python+django/flask基于深度学习的个性化携程美食数据推荐系统
  • VRRP虚拟路由冗余
  • 嵌入式软件OTA升级,有哪几种FLASH划分方式?
  • wordpress 投稿者 权限厦门做网站seo
  • 玩转Rust高级应用 如何避免对空指针做“解引用”操作,在C/C++ 里面就是未定义行为
  • 音视频处理(三):hls协议和m3u8详解和视频下载爬虫实战
  • Java面试全生态图谱(2025体系版)
  • 亳州做网站的公司公司品牌网站建设
  • 泉州网站公司wordpress 搜索乱码