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 Moving | Reason | |
---|---|---|
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;
}