3个题--

1.寻找M [搜索]

在这里插入图片描述

解法1(建议)

#include<stdio.h>
#include<queue>

using namespace std;

int main() {
	queue<long long> num;//创建一个队列
	int n;
	while(~scanf("%lld", &n)) {
		if(n == 0) break;//如果n为0则直接结束程序
		num.push(1);//初始化队列 
		while(!num.empty()) { //队列为空时退出循环 
			long long m = num.front();//取队头元素 
			num.pop();//弹出队头元素
			if(m % n == 0) {
				printf("%lld\n", m);
				break;
			}
            //注意下面两句顺序不能换
			num.push(m * 10 + 1);
            num.push(m * 10);
		} 
	}
	return 0;
}

解法2

#include <iostream>
#include <cstdio>
#include <queue>

using namespace std;

void BFS(int n)
{
	queue <long long > number;
	number.push(1);
	while(!number.empty()){
		long long current = number.front();//先进先出,取队首
		number.pop();  //获取后弹出
		if(current % n == 0){ 
			printf("%lld\n",current);
			return;
		}
		number.push(current *10);
		number.push(current *10 +1);
	}
}

int main()
{
	int n;
	while(scanf("%d",&n) != EOF){
		if(n == 0){
			break;
		}
		BFS(n);
	}
	return 0;
} 

参考:寻找M

2.最长公共子序列 [动态规划]

我们称序列Z = < z1, z2, …, zk >是序列X = < x1, x2, …, xm >的子序列当且仅当存在严格上升的序列< i1, i2, …, ik >,使得对j = 1, 2, … ,k, 有xij = zj。比如Z = < a, b, f, c > 是X = < a, b,c, f, b, c >的子序列。 现在给出两个序列X和Y,你的任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列。

输入格式:

输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

输出格式:

对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。

输入样例:

在这里给出一组输入。例如:

abcfbc abfcab
programming contest
abcd mnp

输出样例:

在这里给出相应的输出。例如:

4
2
0

解法1

#include<iostream>
#include<cmath>
#include<cstring>

#define len 1000

using namespace std;

char s1[len],s2[len];
int maxLen[len][len];

int main()
{
    while(cin>>s1>>s2)
    {
        int len1=strlen(s1);
        int len2=strlen(s2);
        for(int i=0;i<=len1;i++)
            maxLen[i][0]=0;
        for(int j=0;j<=len2;++j)
            maxLen[0][j]=0;
        for(int i=1;i<=len1;++i)
        {
            for(int j=1;j<=len2;j++)
            {
                if(s1[i-1]==s2[j-1])
                    maxLen[i][j]=maxLen[i-1][j-1]+1;
                else
                {
                    maxLen[i][j]=max(maxLen[i][j-1],maxLen[i-1][j]);
                }
            }
        }
         cout<<maxLen[len1][len2]<<endl;
    }
    return 0;
}

3.移动桌子 [贪心]

著名的ACM(Advanced Computer Maker)公司租用了一层有400个房间的办公楼,结构如下。

在这里插入图片描述

这层楼沿着走廊南北向的两边各有200个房间。最近,公司要做一次装修,需要在各个办公室之间搬运办公桌。由于走廊狭窄,办公桌都很大,走廊里一次只能通过一张办公桌。必须制定计划提高搬运效率。经理制定如下计划:一张办公桌从一个房间移动到另一个房间最多用十分钟。当从房间i移动一张办公桌到房间j,两个办公室之间的走廊都会被占用。所以,每10分钟内,只要不是同一段走廊,都可以在房间之间移动办公桌。为了说得更清楚一些,经理举例说明哪些情况可以同时移动,哪些情况不能同时移动。

Table MovingReason
Possible(room 30 to 50) and (room 60 to 90)No part of corridor is shared
(room 11 to 12) and (room 14 to 13)No part of corridor is shared
Impossible(room 20 to 40) and (room 31 to 80)Corridor in front of room 31 to room 40 is shared
(room 1 to 4) and (room 3 to 6)Corridor in front of room 3 is shared
(room 2 to 8) and (room 7 to 10)Corridor in front of room 7 is shared

每个房间,只有一张办公桌进出。现在,经理想找到一种方案,使移动桌子的事情尽快完成。请编写程序解决经理的难题。

输入:

输入数据有T组测试例,在第一行给出测试例个数(T)。每个测试例的第一行是一个整数N(1≤N≤200),表示要搬运办公桌的次数。接下来N行,每行两个正整数s和t,表示一张桌子,是从房间号码s移到房间号码t。有多组输入数据,输入第一行为一个表示输入数据总数的整数N,然后是N组输入数据。

输出:

每组输入都有一行的输出数据,为一整数T,表示完成任务所花费的最少时间。

样例输入:

2 
4 
10 20 
30 40 
50 60 
70 80 
2 
1 3 
2 200 

样例输出:

10
20

解题分析:

在经理给出的说明表格中,已经明确地描述了算法:

(1)(从房间30-50)和(从房间60-90)是允许的,因为没有占用公共的走廊;

(2)(从房间20-40)和(从房间31-80)是不允许的,因为要占用公共的走廊。

我们将每个房间之间的走廊作为一个统计单位,当所有的办公桌都搬运完成之后,看看这段走廊到底需要占用多少次?然后统计所有的走廊被占用的最大值max,这个值就是要单独安排的搬运次数,乘以10就是总的搬运时间。

该算法应该属于贪心算法,因为它尽可能使搬运办公桌同时进行,以便使单独安排的搬运次数最少。

例如样例1:(10,20),(30,40),(50,60)和(70,80),四次搬运都不占用公共的走廊,所以可以同时进行,一次搬运成功。

解法1(建议)

#include<stdio.h>
#include<string.h>

int main() {
	int n,corridor[200],time,tables,x,y,start,end;
	scanf("%d", &n);
	while(n--) {
		memset(corridor, 0, sizeof(corridor));
		time = 0;
		scanf("%d", &tables);
		for(int i = 0; i<tables; i++) {
			scanf("%d%d",&x, &y);
			start = ((x>y ? y : x) - 1)/2;
			end = ((x<y ? y : x) - 1)/2;
			for(int j = start; j<end; j++) {
				corridor[j] += 10;
			}
		}
		for(int i = 0; i<200; i++)  {
			time = corridor[i]>time ? corridor[i] : time;
		}
		printf("%d\n",time);
	}
	
	return 0;
} 

解法2

与解法1思想一样,但是没有解法1简洁。

#include <stdio.h>
#include <memory.h>

int main()
{
	int iCase;		//测试例数
	scanf("%d", &iCase);
	while(iCase--)
	{
		int i,j;
		int move[200];		//每个房间之间一个走廊,一共有200个公共走廊
		int N;				//搬运次数
		int from, to;		//每次搬运的起点和终点
		scanf("%d",&N);
		memset(move, 0, sizeof(move));
		for(i=0; i<N; i++)
		{
			scanf("%d%d", &from, &to);
			from = (from - 1) / 2;	//将房间号折算成走廊号
			to = (to - 1) / 2;
			if(from > to)
			{
				int temp = from;
				from = to;
				to = temp;
			}
			for(j=from; j<=to; j++)	//占用走廊情况
				move[j++];
		}
		int max = 0;
		for(i=0; i<200; i++)		//所有的走廊被占用的最大值
		{
			if(move[i] > max)
			{
				max = move[i];
			}
		}
		printf("%d\n", max * 10);	//总的搬运时间
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值