[ZISUOJ] Constest 1497 Structures

前言

        本文是大学生自己暂时记录代码的用途,并为班级里的同学提供思路,如有错误或者,欢迎指教。

Include

        本文的代码全部使用C++编写,如果有人抱着C还学不会怎么会C++的态度,我只能说用过的人都说“真香”,看不懂的代码本社区也有C++语法的详解。

        本文包括:

  1. P1048 Problem N 金银岛问题(tan9)
  2. P1044 Problem O 活动选择(tan5)
  3. P1927 Problem P 七七七
  4. P1926 Problem Q 六六六


P1048 Problem N 金银岛问题(tan9) 

         本题本质上是一个贪心算法,具体思路是需要构建一个结构体用来存储质量,价值,单价。然后进行排序,从单价最高的金属开始选择。

        这个问题也很简单,就像一对珠宝摆在你面前,你只有一个麻袋,你一定会先选择价值几百万的钻戒,而不是同等价值的水泥。所以要先选择单价比较贵的。

        在排完序后,就可以直接往麻袋里装了,先装贵的,再装便宜的,然后拿不下的切两半(题目中没要考虑金银珠宝切割后的贬值问题)。

        接下来是代码实现:

首先是头文件(C++)

万能头文件里有我们需要用的头文件诸如

#include<cstdio>
// scanf() printf()
#include<iostream>
// cin cout endl
#include<algorithm>
// sort

头文件 

写完之后是这样

#include<bits/stdc++.h>//万能头文件
using namespace std;
const int maxn = 1e4 + 5;//定义一个常量

提示,如果不写using namespace std; 的话 ,那么你的sort就该这么写

std::sort()

结构体 

接下来是金属的结构体,如果感兴趣的同学可以寻找一下关于结构体内函数的用法用来初始化单价,然后这样在main函数中会简单很多。

//定义一个金属的结构体
struct metal{
    double m;//这是整块金属的重量
    double val;//这是整块金属的价值
    double s;//这个是 val / m ,金属的单价(元/g)
}a[maxn];//maxn为上文定义的常量

排序规则

然后此时就需要写一个排序,来实现对于单价的排序。

bool cmp (metal x,metal y)
{
    //进对于单价进行排序,别的不用管
    if(x.s >y.s)
        return true;
    return false;
}

主函数

接下来就是主函数了

在main函数里面,主要是读入数据和说出数据和运算

首先是t组数据,不多讲了

接下来开始读入重要数据,注意要在读入的时候顺便计算一下每件物品的单价

代码实现:

// 你的麻袋有多大?(你有多大胆)
int w;
cin >> w;
// s组数据
int s;
cin >> s;
// 读入数据
for(int i = 1; i <= s; i++)
{
    cin >> a[i].m >> a[i].val;
    // 在读入数据的同时计算单价
    a[i].s = a[i].val / a[i].m;
}

 之后一句排序

sort(a+ 1,a + s +1, cmp);

 排完序之后就可以开始拿了,先整个整个拿吧,可能拿不完,所以需要记录麻袋里宝物的重量和件数

// 现在你麻袋理的东西有多重
double sum = 0;
// 你得到的金银珠宝价值多少(地有多大产)
double ans = 0;
// 记录拿了i件金银珠宝
int i = 1;
// 使劲儿往我麻袋里整个整个扔啊,只要没扔满,没拿完,接着扔。
while(sum < w)
{
    // 实在盛不下了就算了吧
    if(sum + a[i].m > w)
        break;
    sum = sum + a[i].m;
    ans = ans + a[i].val;
    // 拿完了,真开心
    if(i == s)
        break;
    i++;
}

之后有两种可能,整个整个刚好拿满和没有拿满,还需要切割,所以用一个if实现

// 如果拿满了
if(i == s || sum == w)
    printf("%.2lf\n",ans);
// 如果麻袋没拿满,就要开始动手工了
else
{
    // 没装满的还能装多么贵的东西
    double t = (w - sum) * a[i].s;
    // 直接往里面扔啊
    ans = ans + t;
    printf("%.2lf\n",ans);
}

主函数最终代码

int main()
{
    int t;
    cin >> t; 
    while(t--)
    {
        // 你的麻袋有多大?(你有多大胆)
        int w;
        cin >> w;
        // s组数据
        int s;
        cin >> s;
        // 读入数据
        for(int i = 1; i <= s; i++)
        {
            cin >> a[i].m >> a[i].val;
            // 在读入数据的同时计算单价
            a[i].s = a[i].val / a[i].m;
        }
        sort(a+ 1,a + s +1, cmp);
        // 现在你麻袋理的东西有多重
        double sum = 0;
        // 你得到的金银珠宝价值多少(地有多大产)
        double ans = 0;
        // 记录拿了i件金银珠宝
        int i = 1;
        // 使劲儿往我麻袋里整个整个扔啊,只要没扔满,没拿完,接着扔。
        while(sum < w)
        {
            // 实在盛不下了就算了吧
            if(sum + a[i].m > w)
                break;
            sum = sum + a[i].m;
            ans = ans + a[i].val;
            // 拿完了,真开心
            if(i == s)
                break;
            i++;
        }
        // 刚刚好,真不错
        if(i == s || sum == w)
            printf("%.2lf\n",ans);
        // 如果麻袋没拿满,就要开始动手工了
        else
        {
            // 没装满的还能装多么贵的东西
            double t = (w - sum) * a[i].s;
            // 直接往里面扔啊
            ans = ans + t;
            printf("%.2lf\n",ans);
        }
    }
    return 0;
}

以上是N题的解题思路

 P1044 Problem O 活动选择(tan5)

我的思路是模拟,把结束时间晚的事件排在前面,优先选择,然后再判断下一个结束时间晚的事件的开始时间是否被占用,如果被占用就判断下一个

接下来代码只写重要部分

事件的结构体

// 事件的结构体 
struct node{
    int n;// 编号 
    int s;// 开始时间 
    int e;// 结束时间 
}a[maxn];

结束时间排序

// 按照结束时间排序 
int cmp(node x,node y){
    return x.e<y.e;
}

main函数部分代码

之后在main函数里读入数据,进行判断操作

// 排序 
sort(a+1,a+n+1,cmp);

// 先输出结束时间早的事件 
cout<<a[1].n;

// 之后将未安排的时间设置为该事件的结束时间 
num=a[1].e;

// 之后从第二个事件开始,看看开始时间是不是晚于未安排的时间
// 满足条件就数出来 
for (int i=2;i<=n;i++)
{
    if (a[i].s>=num)
    {
        cout<<","<<a[i].n;
        num=a[i].e;
    }
}

 最后得到的结果就是正解

 P1927 Problem P 七七七

这道题的思路其实很简单,比较麻烦的就是那个排序规则。

先是定义这个弹幕的结构体

结构体

// 弹幕的结构体 
struct node{
    string x;// 字符串 
    int y;// 字符串中7的个数 
    int z;// 字符串的长度 
}a[10005], t;

排序规则

之后写,排序算法,优先7多的在前面,然后7少的在后面。

如果7一样多,那么短的字符串在前面

如果还一样长,那么按照字典序排序,直接用string比较便可以得出字典序大小

// 按照 字符串7的个数排序,如果7个数相同,短的在前面 ,否则按照字典序 
int cmp(node c, node d){
    if (c.y == d.y)
	{
        if (c.z != d.z)
		{
            return c.z < d.z;
        }
        if (c.z == d.z)
		{
            return c.x > d.x;
        }
    }
    return c.y > d.y;
}

 然后这里写了一个计算字符串里面7的个数的函数

求7的函数

// 求字符串中7的个数 
int qiu(string b)
{
    int num = 0;
    for (int i = 0; i < b.size(); i++)
	{
        if (b[i] == '7')
		{
            num++;
        }
    }
    return num;
}

main

接下来是main函数,比较简单,直接排个序就好了

int main(){
    int n;
    cin >> n;
    // 读入n组数据 
    for (int i = 1; i <= n; i++)
	{
		// 读入字符串 
        cin >> a[i].x;
        // 计算7的个数 
        a[i].y = qiu(a[i].x);
        // 字符串的长度 
        a[i].z = a[i].x.size();
    }
    // 排序 
    sort(a + 1, a + n + 1, cmp);
	// 直接输出 
    for (int i = 1;i <= n; i++)
	{
        cout << a[i].x << endl;
    }
    return 0;
} 

到此就结束了

 P1926 Problem Q 六六六

这道题的思路跟上一道题是一样的,只不过把字符串换成了数字,更简单了

同样包含以下几个元素

数字的结构体

// 那些数的结构体 
struct node{
    int x;// 数字本体 
    int y;// 数字里面包含6的个数 
}a[maxn];

按照6的个数排序的规则

// 关于6的个数的排序 
int cmp(node c, node d){
    if (c.y != d.y)
	{
        return c.y > d.y;
    }
    // 按照大小排序 
	else 
	{
        return c.x > d.x;
    }
}

求每个数字里面6的个数的函数

// 计算数字里面6的个数 
int qiu(int b)
{
    int num = 0;
    while (b > 0)
	{
        if (b % 10 == 6)
		{
            num++;
        }
        b = b / 10;
    }
    return num;
}

最后是主函数

int main(){
    int n;
    cin >> n;
    // 读入n组数据 
    for (int i = 1; i <= n; i++)
	{
		// 读入数字 
        cin >> a[i].x;
        // 计算6的个数 
        a[i].y = qiu(a[i].x);
       
    }
    // 排序 
    sort(a + 1, a + n + 1, cmp);
	// 直接输出 
    for (int i = 1;i <= n; i++)
	{
        cout << a[i].x << " ";
    }
    cout << endl;
    return 0;
} 

今天的题目结束了,写的不好,欢迎指教

后言

本来打算用markdown写的(昨晚学了一晚上),但是没能找的合适的写blog的网站或者软件,先用CSDN,之后可能会有我自己的blog,

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值