<C/C++算法>九度OJ题目1415--1464解题练习(八)


题目1415:不一样的循环队列

题目描述:

大家都知道数据结构里面有一个结构叫做循环队列。顾名思义,这是一个队列,并且是循环的。但是现在,淘气的囧哥给这个循环队列加上了一些规矩,其中有5条指令:

(1) Push K, 让元素K进队列。

(2) Pop,对头元素出队列。

(3) Query K,查找队列中第K个元素,注意K的合法性

(4) Isempty,判断队列是否为空。

(5) Isfull,判断队列是否已满。

现在有N行指令,并且告诉你队列大小是M。

输入:

第一行包含两个整数N和M。1<=N,M<=100000。

接下来有N行,表示指令,指令格式见题目描述。

其中元素均在int范围。

输出:

对于指令(1),若队列已满,输出failed,否则不做输出。

对于指令(2),若队列已空,输出failed,否则不做输出。

对于指令(3),输出队列中第K个元素,若不存在,输出failed。

对于指令(4)和(5),则用yes或者no回答。

详情见样例。

样例输入:
12 2Push 1Push 2Push 3Query 2Query 3IsemptyIsfullPopPopPopIsemptyIsfull
样例输出:
failed2failednoyesfailedyesno


题目1419:文献排序

题目描述:

现在你的导师给你了一个待排序的参考文献列表,要你排好序给他。

文献列表中每一条文献记录只占一行。排序的规则和string类型字符串的比较规则一致(在排序时如果该字符串中包含大写字母,则当作小写字母处理,保证没有相同大小的字符串,但是输出结果不能改变任一字符串),按升序排列。

输入:

输入包括多组,每组输入第一行包括一个整数n,(1<=n<=200),接下来有n行,每行包括一行文献记录,文献记录的长度s(1<=s<=200)。

输出:

        对每组输入。输出排好序的文献记录。

样例输入:
3abc hello!Abc hellz!bbc hello!
样例输出:
abc hello!Abc hellz!bbc hello!

#include "string"
#include "algorithm"
#include <iostream>
#include "stack"
#include <cmath>
#include <set>

using namespace std;


class NodeStr
{
public:
	string Literature;
	bool operator < (NodeStr modenode)//注意返回值的类型,运算符重载。  
	{
		string tmpliter1 = modenode.Literature;
		string tmpliter2 = Literature;
		for (int i = 0; i < tmpliter1.size(); i++)
		{
			if (tmpliter1[i] >= 65 && tmpliter1[i] <= 90)
				tmpliter1[i] = tmpliter1[i] + 32;
		}

		for (int i = 0; i < tmpliter2.size(); i++)
		{
			if (tmpliter2[i] >= 65 && tmpliter2[i] <= 90)
				tmpliter2[i] = tmpliter2[i] + 32;
		}

		return tmpliter2 < tmpliter1;
	}
};

NodeStr nodestr[100];

int main()
{
	int n = 0;
	while (cin>>n)
	{
		for (int i = 0; i < n; i++)
			cin >> nodestr[i].Literature;
		
		sort(nodestr, nodestr + n);

		for (int i = 0; i < n; i++)
			cout << nodestr[i].Literature << endl;
	}
	return 0;
}


题目1420:Jobdu MM分水果

题目描述:

Jobdu团队有俩PPMM,这俩MM干啥都想一样。一天,富强公司给团队赞助了一批水果,胡老板就把水果派发给了这俩MM,由她们自行分配。每个水果都有一个重量,你能告诉她们怎么分才使得分得的重量差值最小吗?

输入:

        输入有多组数据,每组数据第一行输入水果个数n(1<=n<=100),接下来一行输入n个重量wi(0<=wi<=10^5)。

输出:

对每组输入输出一行,输出可以得到的最小差值。

样例输入:
510 20 30 10 10 
样例输出:
0


参考资源:http://blog.csdn.net/jdplus/article/details/21279141


#include "vector"  
#include <cstdio>
#include <iostream>  
#include "algorithm"  
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
//将问题转化为动态规划:
//假设所有水果总重为sum, 为了两个人分得尽可能相等(差值最小),
//那么其中一个人所能分得的水果重量w范围一定在 (0,sum/2]之间,
//问题就转化为一个人所分得的重量w尽可能接近sum/2。
//令dp[i]表示期望接近的重量值为i时,只对前j个物品进行选择最接近i的值
//(选择出来的重量和不超过i值,但是最接近)
//每一个物品,我们可以选择,也可以不选  ,对物品的选择从一个到所有
//自底向上遍历求解,当期望接近的重量为i,在选择第j个物品时  
//如果选择第j个物品,显然就是当前物品的价值fruit[j]加上最接近i - fruit[j]的值(即dp[i - fruit[j]])
//就是最接近i的值了,即dp[i] =  dp[i - fruit[j]] + fruit[j](i应该递减)
//如果不选,那就没变化,dp[i] = dp[i]  (背包问题里面此时就是f[i][v]=f[i-1][v])
//谁更大,显然就更接近i值
int sum;
 
int getMinDiff(vector<int> &fruit)
{
    int i, j;
    int half = (sum >> 1);
    vector<int> dp(half+1,0);
    for (i = 0; i < fruit.size(); ++i)//水果的选择
    {
        for (j = half; j >= fruit[i]; --j)//计算最接近j重量的值(在选择前i个物品时)
        {
            dp[j] = max(dp[j], dp[j - fruit[i]] + fruit[i]);
        }
    }
    return sum - 2 * dp[half];
}
 
int main(int argc, char *argv[]) 
{
    int n = 0;
    while (scanf("%d", &n) != EOF)
    {
        sum = 0;
        vector<int> vecfruit(n, 0);
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &vecfruit[i]);
            sum += vecfruit[i];
        }
        printf("%d\n", getMinDiff(vecfruit));
    }
 
    return 0;
}
/**************************************************************
    Problem: 1420
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:1110 ms
    Memory:4248 kb
****************************************************************/




题目1434:今年暑假不AC

题目描述:

“今年暑假不AC?”“是的。”“那你干什么呢?”“看世界杯呀,笨蛋!”“@#$%^&*%...”确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)

输入:

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

输出:

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

样例输入:
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
样例输出:
5
#include "vector"
#include "string"
#include "algorithm"
#include <iostream>
#include "stack"
#include <cmath>  
 
using namespace std;
 
int GreedyActSelector(vector<int> &s, vector<int> &f);
 
int main()
{
    int n = 0;
    while (cin >> n&&n <= 1000)
    {
        if (n == 0)
            break;
        vector<int> vecstart(n);
        vector<int> vecend(n);
        //接受开始时间和结束时间
        for (int i = 0; i < n; i++)
            cin >> vecstart[i] >> vecend[i];
        //对其排序,要保证结束时间是有序的,
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                if (vecend[i]>vecend[j])//对结束时间排序,由小到大
                {
                    int temp1 = vecend[i];
                    vecend[i] = vecend[j];
                    vecend[j] = temp1;
 
                    int temp2 = vecstart[i];//开始时间也相应变换,但不一定有序
                    vecstart[i] = vecstart[j];
                    vecstart[j] = temp2;
                }
            }
        }
        cout << GreedyActSelector(vecstart, vecend) << endl;
    }
    return 0;
}
//以第一个节目作为起点(为了能保证他是最早的对其排序。所以因为他是最早结束的,这样才可以尽可能增加多次活动的“潜力”),
//总是选择满足兼容条件下的最早结束的节目,因为这样可以使得剩下的时间资源看其他节目,
//这种选择方式一定可以选出最大的兼容节目数量。
int GreedyActSelector(vector<int> &start, vector<int> &finish)
{
    int longlen = 0;
    int k = 0;//记录最近加入的节目的下标  
    int count = 1;
    for (int m = 1; m < start.size(); m++)
    {//start[m]是下一个节目的开始时间,finish[k]是上一个节目的结速时间,
        //我们总贪婪的找到下一个节目的开始时间比上一个的结束时间大  
        if (start[m] >= finish[k])
        {
            count++;
            k = m;
        }
    }
    return count;
}
/**************************************************************
    Problem: 1434
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/


题目1438:最小公倍数

题目描述:

给定两个正整数,计算这两个数的最小公倍数。

输入:

输入包含多组测试数据,每组只有一行,包括两个不大于1000的正整数。

输出:

对于每个测试用例,给出这两个数的最小公倍数,每个实例输出一行。

样例输入:
10 14
样例输出:
70
#include <iostream>
 
using namespace std;
 
int main() 
{
    int a, b;
    while (cin >> a >> b && a >= 1 && a <= 1000 && b >= 1 && b <= 1000)
    {
        int minGcd = 0;
        if (a>b)
            minGcd = a;
        else
            minGcd = b;
        while (minGcd%a != 0 || minGcd%b != 0)
            minGcd++;
             
        cout << minGcd << endl;
    }
     
    return 0;
}
/**************************************************************
    Problem: 1438
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:120 ms
    Memory:1520 kb
****************************************************************/


题目1458:汉诺塔III

题目描述:

约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?

输入:

包含多组数据,每次输入一个N值(1<=N=35)。

输出:

对于每组数据,输出移动最小的次数。

样例输入:
1
3
12
样例输出:
2
26
531440

#include <iostream>
#include "stack"
#include <cmath>
#include <set>
 
using namespace std;
 
long long F(int num)
{ 
    if (num == 1) 
        return 2;
    else
        return 3 * F(num - 1) + 2;
}
int main()
{
    int n;
    while (cin>>n)
        cout << F(n) << endl;
    return 0;
}
/**************************************************************
    Problem: 1458
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/


题目1462:两船载物问题

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:983

解决:285

题目描述:

给定n个物品的重量和两艘载重量分别为c1和c2的船,问能否用这两艘船装下所有的物品。

输入:

输入包含多组测试数据,每组测试数据由若干行数据组成。
第一行为三个整数,n c1 c2,(1 <= n <= 100),(1<=c1,c2<=5000)。
接下去n行,每行一个整数,代表每个物品的重量(重量大小不大于100)。

输出:

对于每组测试数据,若只使用这两艘船可以装下所有的物品,输出YES。
否则输出NO。

样例输入:
3 5 8
6
3
3
3 5 8
5
3
4
样例输出:
NO
YES

#include "vector"  
#include <iostream>  
#include "algorithm"  
#include <stdio.h>  
#include <string.h> 
using namespace std;
 
//将问题转化为动态规划:  
//假设所有物品总重为sum, 为了两个船装的下,必须sum<c1+c2,  
//那么其中载物重量较小的那艘船(令其为c1)尽可能装接近其载物量c1的物品总量和 
//问题就转化为选择所有物品尽可能接近c1 (意义就是小船尽可能多装,为什么选择小船?内存消耗较小)
//令dp[i]表示期望接近的重量值为i时,只对前j个物品进行选择时最接近i的值  
//选择出来的重量和不超过i值,但是是基于前j个物品最接近
//每一个物品,我们可以选择,也可以不选  ,对物品的选择从一个到所有  
//自底向上遍历求解,当期望接近的重量为i,在选择第j个物品时    
//如果选择第j个物品,显然就是当前物品的重量weightlist[j]加上最接近i - weightlist[j]的值(即dp[i - weightlist[j]])  
//就是最接近i的值了,即dp[i] =  dp[i - weightlist[j]] + weightlist[j](i应该递减)  
//如果不选,那就没变化,dp[i] = dp[i]  (背包问题里面此时就是f[i][v]=f[i-1][v])  
//最后小船已经装载了dp[c1],那么如果大船只要再装sum-dp[c1],所以大船的载重量c2必须大于这个差值
 
 
int main()
{
    int  c1, c2, sum, n;
    while (~scanf("%d %d %d", &n, &c1, &c2))
    {
        sum = 0;
        vector<int> weightlist(n + 1, 0);
        //接受输入
        for (int i = 1; i <= n; i++)
        { 
            scanf("%d", &weightlist[i]);
            sum += weightlist[i];
        }
        if (c1 + c2<sum)
        { //物品的总重量大于两首船的载重
            puts("NO"); 
            continue; 
        }
        //总是让c1成为较小者为了,总是先装载物较小的船
        if (c1>c2)
        { 
            int tmp = c1; 
            c1 = c2; 
            c2 = tmp; 
        }
        vector<int> dp(c1+1, 0);
        for (int i = 1; i <= n; i++)
            for (int j = c1; j >= weightlist[i]; j--)
                dp[j] = max(dp[j - weightlist[i]] + weightlist[i], dp[j]);
         
        if (c2 + dp[c1]<sum)
            puts("NO");
        else
            puts("YES");
    }
    return 0;
}
/**************************************************************
    Problem: 1462
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1520 kb
****************************************************************/




题目1463:招聘会

题目描述:

又到毕业季,很多大公司来学校招聘,招聘会分散在不同时间段,小明想知道自己最多能完整的参加多少个招聘会(参加一个招聘会的时候不能中断或离开)。

输入:

第一行n,有n个招聘会,接下来n行每行两个整数表示起止时间,由从招聘会第一天0点开始的小时数表示。
n <= 1000 。

输出:

最多参加的招聘会个数。

样例输入:
3
9 10
10 20
8 15
样例输出:
2


#include <iomanip>//小数点精确
#include "vector"
#include "string"
#include "algorithm"
#include <iostream>
 
#include <cstdio>
using namespace std;
int GreedyActSelector(vector<int> &s, vector<int> &f);
int main()
{
    int n = 0;
    while (cin >> n&&n <= 1000)
    {
        vector<int> vecstart(n);
        vector<int> vecend(n);
 
        for (int i = 0; i < n; i++)
            cin >> vecstart[i] >> vecend[i];
        for (int i = 0; i < n; i++)
        {
            for (int j = i+1; j < n; j++)
            {
                if (vecend[i]>vecend[j])//对结束时间排序,由小到大
                {
                    int temp1 = vecend[i];
                    vecend[i] = vecend[j];
                    vecend[j] = temp1;
 
                    int temp2 = vecstart[i];//开始时间也相应变换,但不一定有序
                    vecstart[i] = vecstart[j];
                    vecstart[j] = temp2;
                }
            }
        }
        cout << GreedyActSelector(vecstart, vecend) << endl;
    }
    return 0;
}
//以第一个招聘会作为起点(因为他是最早结束的,这样才可以尽可能增加多次活动的“潜力”),
//总是选择满足兼容条件下的最早结束的活动,因为这样可以使得剩下的时间资源可以更多的其他活动使用,
//这种选择方式一定可以选出最大兼容活动数。
int GreedyActSelector(vector<int> &start, vector<int> &finish)
{
    int longlen = 0;
    int k = 0;//记录最近加入的活动的下标  
    int count = 1;
    for (int m = 1; m < start.size(); m++)
    {
        if (start[m] >= finish[k])//start[m]是下一个活动的开始时间,finish[k]是上一个活动的结速时间,我们总贪婪的找到下一个活动的开始时间比上一个的结束时间大  
        {
            count++;
            k = m;
        }
    }
    return count;
}
/**************************************************************
    Problem: 1463
    User: EbowTang
    Language: C++
    Result: Accepted
    Time:20 ms
    Memory:1520 kb
****************************************************************/




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值