算法分析与设计 专题三

目录

一、实验目的

二、实验内容

三、问题分析与求解

四、AC源代码、截图

五、实验小结


一、实验目的

1、了解贪心算法的分析过程,学会用贪心算法解决一些具体的问题。

2、了解广度优先算法和深度优先算法。

、实验内容

  1. 1992

当然,我们的收藏中至少需要一个电脑游戏。典型的可以说是“镇上追逐”。在我们的案例中,笑脸叫杰克,正在穿过分成小田野的小镇。有些田地被墙覆盖,无法穿过它们。杰克收集积分,并试图避免与追逐他的怪物接触。一旦杰克吃了特殊点(或星号),情况就会颠倒过来,杰克可以吃怪物。以此类推,一次又一次。我相信你们每个人都见过这样的游戏。

在我们的例子中,城镇是随机生成的。杰克总是从左上角开始,“奖励星号”在右下角。在最困难的关卡中,只要杰克只向左和向下走几步,奖金就会消失,这些步数恰好足以从一个角落到另一个角落。如果他朝着错误的方向迈出一步,他永远无法及时到达那里。但防止被怪物抓住仍然很重要。因此,玩家必须选择最好的方式到达右下角。你要确定镇上有多少种不同的方式。

  1. 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只能求满足某些约束条件的可行解的范围

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值