ACM 2020年3月15号总结

STL

STL简单应用(都写下来太乱,就令写了一篇博客)
反思总结
  1. 对于STL中的成员很多操作都是通用的
    比如empty,size。
    但对于每一个成员,根据其性质不同也有其特殊的操作,比如stack (因为只能一头进和出,所以只能操作栈顶)。要想熟练地使用STL,对于每个成员各自的性质以及不同的操作一定要各自记准确了,防止用串了。
  2. 迭代器
    所有成员的迭代器操作都是一样的
    以multiset为例:
multiset<int>:: iterator pos;//::iterator pos;是一样的
for(pos=s.begin();pos!=s.end();pos++)

贪心算法

oj习题
1

01:An Easy Problem
we known, data stored in the computers is in binary form. The problem we discuss now is about the positive integers and its binary form.
Given a positive integer I, you task is to find out an integer J, which is the minimum integer greater than I, and the number of '1’s in whose binary form is the same as that in the binary form of I.
For example, if “78” is given, we can write out its binary form, “1001110”. This binary form has 4 '1’s. The minimum integer, which is greater than “1001110” and also contains 4 '1’s, is “1010011”, i.e. “83”, so you should output “83”.
输入
One integer per line, which is I (1 <= I <= 1000000).
A line containing a number “0” terminates input, and this line need not be processed.
输出
One integer per line, which is J.

样例输入
1
2
3
4
7
0`
样例输出
2
4
5
8
83

#include<iostream>
using namespace std;

int two(int x)
{
    int tot=0;
    while(x)
    {
    if(x%2)
    tot++;
    x/=2;
    }
    return tot;

}
int main()
{int m;
while(1)
{cin>>m;
if(m==0)return 0;
    int t=m+1;
    int a=two(m);
    for(int i=t;;i++)
    {
        if(two(i)==a)
        {
            cout<<i<<endl;
            break;
        }
    }

}

}
总结

这个题贪心思想不难,就是从最接近所给的数往上找,找到的第一个肯定是最小的。但是竟然被化二进制卡了,基础不牢,地动山摇

2

03:金银岛
飞行器飞到了一个金银岛上,上面有许多珍贵的金属,KID虽然更喜欢各种宝石的艺术品,可是也不拒绝这样珍贵的金属。但是他只带着一个口袋,口袋至多只能装重量为w的物品。岛上金属有s个种类, 每种金属重量不同,分别为n1, n2, … , ns,同时每个种类的金属总的价值也不同,分别为v1,v2, …, vs。KID想一次带走价值尽可能多的金属,问他最多能带走价值多少的金属。注意到金属是可以被任意分割的,并且金属的价值和其重量成正比。

输入
第1行是测试数据的组数k,后面跟着k组输入每组测试数据占3行,第1行是一个正整数w (1 <= w <= 10000),表示口袋承重上限。第2行是一个正整数s (1 <= s <=100),表示金属种类。第3行有2s个正整数,分别为n1, v1, n2, v2, … , ns, vs分别为第一种,第二种,…,第s种金属的总重量和总价值(1 <= ni <= 10000, 1 <= vi <= 10000)。
输出
k行,每行输出对应一个输入。输出应精确到小数点后2位。
样例输入
2
50
4
10 100 50 30 7 34 87 100
10000
5
1 43 43 323 35 45 43 54 87 43

样例输出
171.93
508.00

#include<iostream>
#include<iomanip>
#include<algorithm>
using namespace std;
struct jinshu
{
    int n,v;
    double xjb;
};

bool cmp(jinshu a,jinshu b)
{
    return a.xjb>b.xjb;
}
int main()
{int k;
cin>>k;
for(int i=1;i<=k;i++)
{
    int w,s;
    cin>>w;
    cin>>s;
     jinshu x[10005];
    for(int j=1;j<=s;j++)
    {cin>>x[j].n>>x[j].v;
    x[j].xjb=(x[j].v*1.0)/(x[j].n*1.0);
    }
    sort(x+1,x+1+s,cmp);
    /*for(int j=1;j<=s;j++)
    cout<<x[j].xjb<<' ';
    cout<<endl;*/

    double all=0;
    for(int j=1;j<=s;j++)
    {
       if(w==0)break;
       else
        {if(w>x[j].n)
        {
            w-=x[j].n;
            all+=x[j].v;
        }
        else
        {

            all+=x[j].xjb*w;
            w=0;

        }
        }
    }

   cout<<fixed<<setprecision(2)<<all<<endl;
}

}
总结

这个题贪心思想很简单:属于性价比问题,就是疯狂地装性价比最高的,因为是可以任意切割的,这点很重要,如果不能任意切割就成dp了,因为要考虑性价比高的不能正好填满整个背包,很有可能有空余空间。一定要注意是否可以任意切割。

3

最短前缀
前缀是从该字符串的第一个字符起始的一个子串。例如 “carbon"的字串是: “c”, “ca”, “car”, “carb”, “carbo”, 和 “carbon”。注意到这里我们不认为空串是字串, 但是每个非空串是它自身的字串. 我们现在希望能用前缀来缩略的表示单词。例如, “carbohydrate” 通常用"carb"来缩略表示. 现在给你一组单词, 要求你找到唯一标识每个单词的最短前缀
在下面的例子中,“carbohydrate” 能被缩略成"carboh”, 但是不能被缩略成"carbo" (或其余更短的前缀) 因为已经有一个单词用"carbo"开始
一个精确匹配会覆盖一个前缀匹配,例如,前缀"car"精确匹配单词"car". 因此 “car” 是 "car"的缩略语是没有二义性的 , “car”不会被当成"carriage"或者任何在列表中以"car"开始的单词.

输入
输入包括至少2行,至多1000行. 每行包括一个以小写字母组成的单词,单词长度至少是1,至多是20.
输出
输出的行数与输入的行数相同。每行输出由相应行输入的单词开始,后面跟着一个空格接下来是相应单词的没有二义性的最短前缀标识符。
样例输入
carbohydrate
cart
carburetor
caramel
caribou
carbonic
cartilage
carbon
carriage
carton
car
carbonate

样例输出
carbohydrate carboh
cart cart
carburetor carbu
caramel cara
caribou cari
carbonic carboni
cartilage carti
carbon carbon
carriage carr
carton carto
car car
carbonate carbona

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;

int main()
{string str[1005];
int i=0;
while(cin>>str[i])
{
    i++;
}
for(int j=0;j<=i;j++)
{
    for(int k=0;k<str[j].size();k++)
    {   if(k==(str[j].size()-1))
         {
           cout<<str[j]<<" "<<str[j].substr(0,k+1)<<endl;
           break;
         }
        bool a=false;
        for(int l=0;l<=i;l++)
        {if(l==j)continue;
            if(str[j].substr(0,k+1)==str[l].substr(0,k+1))
            {a=true;
                break;
            }
        }
        if(!a)
        {cout<<str[j]<<" "<<str[j].substr(0,k+1)<<endl;
         break;
        }
    }
}
}
总结

这个题不知道贪心思想在哪,我看了半天也没看出来(水平太低?),就一个串一个串暴力循环来做的,string是真好用啊,回头一定要记熟了,老查书太费劲了

5

05:装箱问题

制造的产品形状都是长方体,它们的高度都是h,长和宽都相等,一共有六个型号,他们的长宽分别为11, 22, 33, 44, 55, 66。这些产品通常使用一个 66h 的长方体包裹包装然后邮寄给客户。因为邮费很贵,所以工厂要想方设法的减小每个订单运送时的包裹数量。他们很需要有一个好的程序帮他们解决这个问题从而节省费用。现在这个程序由你来设计。

输入
输入文件包括几行,每一行代表一个订单。每个订单里的一行包括六个整数,中间用空格隔开,分别为11至66这六种产品的数量。输入文件将以6个0组成的一行结尾。
输出
除了输入的最后一行6个0以外,输入文件里每一行对应着输出文件的一行,每一行输出一个整数代表对应的订单所需的最小包裹数。
样例输入
0 0 4 0 0 1
7 5 1 0 0 0
0 0 0 0 0 0
样例输出
2
1

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;

int main()
{
    int a,b,c,d,e,f;
    while(cin>>a>>b>>c>>d>>e>>f)
    {
        if(a==0&&b==0&c==0&&d==0&&e==0&&f==0)
            return 0;
        int sum=0,r1=0,r2=0;
        sum+=f+e+d+(c+3)/4;
        if((c+3)/4*4-c==1)
        {r2=d*5+1;
        r1=e*11+5;}
        if((c+3)/4*4-c==2)
        {r2=d*5+3;
        r1=e*11+6;
        }
        if((c+3)/4*4-c==3)
        {r2=d*5+5;
        r1=e*11+7;}
        if((c+3)/4*4-c==0)
        {r2=d*5;
        r1=e*11;}
        if(r2>=b)
        {
            r1+=(r2-b)*4;
            if(r1<a)
            {
                sum+=(a-r1+35)/36;
            }
        }
        else
        {
            sum+=(b-r2+8)/9;
            r1+=((b-r2+8)/9*9-(b-r2))*4;
            if(r1<a)
            {
                sum+=(a-r1+35)/36;
            }
        }


        cout<<sum<<endl;
    }
}
总结

贪心思想:先装大的,再用小的填补大的装剩下的空
难在用代码实现上

还做了一个 书架和寻找平面上极值点的问题,因为太简单了,没什么整理的必要,就不整理了

感悟

贪心的题难起来真的没边了,好多题都是一想想半天都没思路,做的题也都是偏简单的,真的是做题太少了,见的少,真的得端正态度,认真总结好每一个见过做过的题,多写写题解,也有助于自己理解的更深一点,老师都说ACM没有范围了,就不能把眼光只放在课堂上,闲暇时光利用起来多看点,多积累一点,量变肯定会引起质变的,别放弃,生死看淡,不服就干,奥里给!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值