目录
一、实验目的
二、实验内容
三、问题分析与求解
四、AC源代码、截图
五、实验小结
一、实验目的
1、了解贪心算法的分析过程,学会用贪心算法解决一些具体的问题。
2、了解广度优先算法和深度优先算法。
二、实验内容
- 1992
当然,我们的收藏中至少需要一个电脑游戏。典型的可以说是“镇上追逐”。在我们的案例中,笑脸叫杰克,正在穿过分成小田野的小镇。有些田地被墙覆盖,无法穿过它们。杰克收集积分,并试图避免与追逐他的怪物接触。一旦杰克吃了特殊点(或星号),情况就会颠倒过来,杰克可以吃怪物。以此类推,一次又一次。我相信你们每个人都见过这样的游戏。
在我们的例子中,城镇是随机生成的。杰克总是从左上角开始,“奖励星号”在右下角。在最困难的关卡中,只要杰克只向左和向下走几步,奖金就会消失,这些步数恰好足以从一个角落到另一个角落。如果他朝着错误的方向迈出一步,他永远无法及时到达那里。但防止被怪物抓住仍然很重要。因此,玩家必须选择最好的方式到达右下角。你要确定镇上有多少种不同的方式。
- 1042
约翰要去钓鱼。他有 h 小时可用 (1 <= h <= 16),该地区有 n 个湖泊 (2 <= n <= 25),都可以沿着一条单行道到达。约翰从1号湖开始,但他可以在任何他想要的湖结束。他只能从一个湖到下一个湖,但除非他愿意,否则他不必在任何湖停留。对于每个 i = 1,...,n - 1,从湖泊 i 到湖泊 i + 1 所需的 5 分钟间隔数表示为 ti (0 < ti <=192)。例如,t3 = 4 表示从湖 3 到湖 4 需要 20 分钟。为了帮助计划他的钓鱼之旅,约翰收集了一些关于湖泊的信息。对于每个湖泊i,预计在最初的5分钟内捕获的鱼的数量,记作fi(fi >= 0),是已知的。
每钓鱼 5 分钟,预计在接下来的 5 分钟间隔内捕获的鱼数量就会以恒定的 di (di >= 0) 速率减少。如果预计在一个区间内捕获的鱼的数量小于或等于di,则在下一个区间内湖中将不再有鱼。为了简化计划,约翰假设没有其他人会在湖边钓鱼,以影响他预计捕获的鱼的数量。
编写一个程序来帮助约翰计划他的钓鱼之旅,以最大限度地增加预期捕获的鱼的数量。在每个湖泊花费的分钟数必须是 5 的倍数。
三、问题分析与求解
1.1992分析与求解:
这道题是问你有多少种能最快到达终点的方法。注意这里的最快不是相对是最快。而是路线只能向右或者向下 不允许向上或者向左走。
2.1042分析与求解:
我们可以把总时间分为两个部分:在路上的时间和在钓鱼的时间。由于路是单行的,所以在路上的时间取决于走的最远距离,即到达的池塘的最大编号。 剩余的时间用于钓鱼。我们可以把移动+钓鱼的混合过程拆分为移动的过程和钓鱼的过程,即指定一个池塘为终点,移动过程即从起点到终点的过程,钓鱼的过程就是从起点到终点的各个池塘中选择池塘钓鱼,因为移动过程所需的时间已经在前面考虑过了,这个时候我们就可以认为需要移动的时候可以直接瞬间到达。然后,选择到哪些池塘钓鱼的策略采用贪心的方法,每个钓鱼的5分钟都选择期望最大的那一个池塘,每在选择一个池塘钓鱼5分钟,减少相应池塘的期望,增加计划中在该池塘钓鱼的时间,然后继续选择期望最大的池塘,直到钓鱼的时间不够,或者池塘里没有鱼了。如果池塘没有鱼了,还有时间的话,把多余的时间分配给第一个池塘。
四、AC源代码、截图
#include<stdio.h>
#include<malloc.h>
#include<string.h>typedef struct{int x, y;
}Point;typedef struct{Point Q[1100];int top, tail;
}Que;
Que q;void ini() {q.top = 0, q.tail = 0;}
void push(int x, int y) {q.Q[q.tail].x = x, q.Q[q.tail].y = y;q.tail++; if(q.tail > 1099) q.tail = 0;}
Point pop() {Point tt; tt = q.Q[q.top++]; if(q.top > 1099) q.top = 0; return tt;}
bool empty() {if(q.tail == q.top) return 1; return 0;}int R, S;
bool map[1005][1005];
int f[1005][1005];int main()
{int Case;int i, j;char x;Point tt;while(scanf("%d", &Case) != EOF){while(Case--){scanf("%d%d", &R, &S);for(i = 0; i < R; ++i){getchar();for(j = 0; j < S; ++j){scanf("%c", &x);map[i][j] = (x == '.'? 1 : 0);f[i][j] = 0;}}push(0, 0);f[0][0] = 1;while(!empty()){tt = pop();if(map[tt.x + 1][tt.y]){if(!f[tt.x + 1][tt.y]) push(tt.x + 1, tt.y);f[tt.x + 1][tt.y] += f[tt.x][tt.y];}if(map[tt.x][tt.y + 1]){if(!f[tt.x][tt.y + 1]) push(tt.x, tt.y + 1);f[tt.x][tt.y + 1] += f[tt.x][tt.y];}}printf("Existuje %d ruznych cest.\n", f[R - 1][S - 1]);}}return 0;
}
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;const int N=25;
int n,h;
int f[N],d[N],t[N];//f第一个五分钟钓的鱼量,d为每个五分钟减少的鱼量,t为i到i+1五分钟的个数
int ans;
int each[N];//记录最终每条湖用的时间
int tans,teach[N];//最优钓鱼量和各湖钓鱼时间
int th,tf[N];//有效钓鱼时间和每条湖前五分钟的钓鱼量 int main()
{int i,j;while(cin>>n&&n>0){//当湖的数量为0的时候结束 cin>>h;//输入时间 for(i=0;i<n;i++){cin>>f[i];//第一次的鱼量 } for(i=0;i<n;i++){cin>>d[i];//每五分钟减少的鱼量 }for(i=0;i<n-1;i++){cin>>t[i];//每个湖间距离需要的时间片 }h*=12;//一小时12个时间片ans=-1;for(i=0;i<n;i++){//表示再第i条湖停下来 //初始化每一次贪心th=h;//有效时间先初始化为总时间 for(j=0;j<n;j++){tf[j]=f[j];//每条湖初始的钓鱼量初始为第一次五分钟的钓鱼量 teach[j]=0;//每个湖的钓鱼时间初始化为0 } tans=0;//最大钓鱼数初始化为0 //对每五分钟贪心选择钓鱼量最大的湖钓鱼 while(th>0){//当有效时间大于0 int ind=0,max=tf[0];//令第一条湖的鱼量为最大值 ,ind标记湖是第几条湖 for(j=0;j<=i;j++){if(tf[j]>max){//不考虑顺序先找第一次鱼量最大的湖 max=tf[j];ind=j;}}if(max==0){//最大钓鱼量为0时,将剩余的钓鱼时间加到第一个湖上的钓鱼时间 teach[0]+=th*5;//例如样例一 break;}else{teach[ind]+=5;//最大湖的钓鱼时间,每钓一次加一次五 tans+=tf[ind];//加上最大鱼量的湖的该次的鱼数 if(tf[ind]>=d[ind])//如果鱼量不少于减少的鱼数 ,则减 {tf[ind]-=d[ind];}else{tf[ind]=0;//小于减少数则赋值为0 }} th--;//有效时间减少一个时间片(一个时间片五分钟) }if(i!=n-1){//i的话是表示在第i条湖停下来 h-=t[i];//减去到下一条湖的时间片 }if(tans>ans){//如果值大于前面的值,就把值赋给ans ans=tans;for(j=0;j<n;j++){each[j]=teach[j];//记录最终每条湖用的时间 }}} cout<<each[0]; for(i=1;i<n;i++){cout<<", "<<each[i];}cout<<endl;cout<<"Number of fish expected: "<<ans<<endl;cout<<endl;}return 0;
}
五、实验小结
1.迷宫问题最短路径问题中,每次处理的位置所对应的距离是严格递增的,因此,一旦找到终点,当前的距离就是最短距离,
搜索可移动到的位置中,判断条件不仅仅是不碰壁不超边界,还有一个条件就是没有到达过。因为,如果已经到达了这个位置,这说明已经有更短的路径到达了这个位置,这次到达这个位置的路径是更远的,不可能达到最优解;
2.贪心算法存在的问题:
(1)不能保证求得的最后解是最佳的;
(2)不能用来求最大值或最小值的问题;
(3)只能求满足某些约束条件的可行解的范围。