寒训记录-2021-1-28/27/26

记录不会做的题,贴代码,写题解
vj贪心专题链接

Packets cf1037A

题意:
有一堆横截面为1×1, 2×2, 3 × 3, 4 × 4, 5 × 5, 6 × 6的物品,问至少需要多少个横截面为6×6的盒子才能装下?(盒子和物品高度相同);多组输入。

基本思路:
先装大的,再用小的填充。贪心思维体现在:尽量装满每个盒子。

就是简单模拟,运用贪心思想,把基本需求列出来就好了。主要是细心。看看别人的博客,有人的ac代码很短,我也学习学习。
一开始错了一个很简单的地方。。WA了好久,难受。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <map>
#include <stdlib.h>
#define MAX_N 1e8+7
#define ll long long

using namespace std;


int main()
{
    int a[10];
    while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])!=EOF)
    {
        if(a[1]==0 && a[2]==0 && a[3]==0 && a[4]==0 && a[5]==0 && a[6]==0)
            break;
        ll ans=0;
        //先装大的,再装小的
        ans+=a[6];
        ans+=a[5];
        //5+1
        a[1]-=a[5]*11;
        ans+=a[4];
        ll left4=a[4]*20;
        //4+2+1
        if(a[2]<a[4]*5)
        {
            left4-=a[2]*4;
            a[2]=0;
        }
        else
        {
            a[2]-=a[4]*5;
            left4=0;
        }
        a[1]-=left4;
        //3+2+1
        ans+=a[3]/4;
        ll leftof3=a[3]%4;
        if(leftof3==1)
        {
            ll left3=27;
            ans++;
            if(a[2]>=5)
            {
                a[2]-=5;
                left3=7;
            }
            else
            {
                left3-=a[2]*4;
                a[2]=0;
            }
            a[1]-=left3;
        }
        if(leftof3==2)
        {
            int left3=18;
            ans++;
            if(a[2]>=3)
            {
                a[2]-=3;
                left3=6;
            }
            else
            {
                left3-=a[2]*4;
                a[2]=0;
            }
            a[1]-=left3;
        }
        if(leftof3==3)
        {
            int left3=9;
            ans++;
            if(a[2]>=1)
            {
                a[2]-=1;
                left3=5;
            }
            a[1]-=left3;
        }
        //2+1
        int left2=0;
        if(a[2]>0)
        {
            if(a[2]%9!=0){
                ans+=a[2]/9+1;
                left2=36-(a[2]%9)*4;
            }
            else{
                ans+=a[2]/9;
            }
        }
        //最后剩下的1
        if(a[1]>0)
        {
            a[1]-=left2;
            if(a[1]>0){
                if(a[1]%36!=0){
                    ans+=a[1]/36+1;
                }
                else{
                    ans+=a[1]/36;
                }
            }
        }
        cout<<ans<<endl;
    }
}

以上是我的ac代码,顺着思路写的,很长很麻烦。。。

一会学习一下别人的好代码。

————————————
————————————
WOW Factor cf1178B

题意:
按照上述规则,寻找字符串中有多少个“WOW”

基本思路:
对每个‘o’分析在前/后共有多少个符合要求的’w’

代码:

char a[1000007];
ll cntwl[1000007];
ll cntwf[1000007];
int main()
{
    scanf("%s",a);
    int n=(int)strlen(a);
    ll sum=0;
    ll cnto=0;
    for(int i=0;i<n;i++){
        if(a[i]=='o')
            cnto++;
    }
    ll l=0;
    ll cntoo;
    cntoo=0;
    for(int i=0;i<n;i++){
        if(a[i]=='v'&&a[i-1]=='v'&&i>0){
            l++;
        }
        if(a[i]=='o'){
            cntoo++;
            cntwl[cntoo]=l;
        }
    }
    ll f=0;
    cntoo=cnto;
    for(int i=n-1;i>0;i--){
        if(a[i]=='v'&&a[i-1]=='v'){
            f++;
        }
        if(a[i]=='o'){
            cntwf[cntoo]=f;
            cntoo--;
        }
    }
    for(int i=1;i<=cnto;i++){
        //cout<<i<<' '<<"cntwl[i]="<<cntwl[i]<<endl;
        //cout<<i<<' '<<"cntwf[i]="<<cntwf[i]<<endl;
        sum+=cntwl[i]*cntwf[i];
    }
    cout<<sum<<endl;
}

第一次写,TLE了,因为写法复杂度最高达到n^2。。多次重复计算,知道错了!

第二次思路没有问题,但是在一个细节处WA了,因为没有考虑‘o’在开头的情况

——————————
——————————
一个奇妙的超傻的题让我想思考关于浮点数的问题
cf 1199B
反正就是直接输出方程结果,要求误差小于10e-6
浮点数到底怎么搞啊。。
在这里插入图片描述
在这里插入图片描述
x用十进制精确表达的数值是8/3,也就是2.6666666666666(循环),这组数据中浮点输出在小数点后15位开始不精确,测试了更多的输出位数,如图
在这里插入图片描述在这里插入图片描述
可以得出一点小结论:
double类型浮点数在小数点后十几位开始不精确;
浮点数用printf输出的时候会四舍五入

——————————
——————————
Minimize the Permutation
cf1256B
得到字典序最小的数字,而且限制移动次数,那么就得让每个位置能移动的最小的数向前移。
从后往前遍历,如果前面的比后面的小,交换位置,同时标记交换的坐标,因为每个坐标只能移动一次。这样可以保证小数字尽量向前移,而且不浪费每一个移动的机会;
然后再从前往后遍历一次,因为上一次遍历时,如果前一位小于后一位,那这个坐标的移动机会便没有被使用,而且通过后续操作,上一次较小的数字可能已经往前移动,更新了数据,上一次较大也有可能继续前移。

int main()
{
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int a[107];
        int b[107]={0};
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=n-1;i>=1;i--){
            if(a[i+1]<a[i] && b[i]==0){
                swap(a[i+1],a[i]);
                b[i]=1;
            }
        }
        for(int i=1;i<=n-1;i++){
            if(a[i+1]<a[i] && b[i]==0){
                swap(a[i+1],a[i]);
            }
        }
        for(int i=1;i<=n;i++){
            cout<<a[i]<<' ';
        }
        cout<<endl;
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KaaaterinaX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值