18/10/19 周五集训队测试赛补题题解

本文深入解析了ACM竞赛中的典型算法题目,包括成绩计算、棋盘DFS、反向筛选、图书查询等,提供了详细的代码实现及算法思路,是算法学习者不可多得的参考资料。

A.成绩

签到题不多说注意用double就行

代码

#include <iostream>
using namespace std;
main()
{
    double a,b,c;
    cin>>a>>b>>c;
    double d=a*0.2+b*0.3+c*0.5;
    printf("%.0lf",d);
}

B.棋盘

DFS+剪枝,特别的地方在于魔法的使用,因为DFS的特殊性,魔法用bool表示的上一个格子是不是已经使用了魔法

代码

#include <bits/stdc++.h>
using namespace std;
int f[110][110];
int mp[110][110];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
int inf=INT_MAX;
int m,n,ans=inf;
void dfs(int x,int y,int sum,bool magic)
{
    if(x<1||y<1||x>m||y>m)//判断边界 
    return;
    if(!mp[x][y])//判断是否有颜色,只能站在有颜色的格子上 
    return;
    if(sum>=f[x][y])//判断记忆数组,如果总和大于记忆数组,那么剪枝 
    return;
    f[x][y]=sum;
    if(x==m&&y==m)//正常的结束 
    {
        if(sum<ans)
        ans=sum;
        return;
    }
    for(int i=0;i<4;i++)//四向dfs的套路写法 
    {
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(mp[xx][yy])//如果格子有颜色 
        {
            if(mp[xx][yy]==mp[x][y])//相等不用花费金币,否则花费一个金币 
            dfs(xx,yy,sum,false);
            else
            dfs(xx,yy,sum+1,false);
        }
        else if(!mp[xx][yy]&&!magic)//如果格子没有颜色且还能用魔法(上一格没有用魔法) 
        {
            mp[xx][yy]=mp[x][y];
            dfs(xx,yy,sum+2,true);
            mp[xx][yy]=0;
        }
    }
}
main()
{
    memset(f,0x7f,sizeof(f));//这里0x7f代表127,代表着把二维数组f都初始化为极大值仅仅比INT_MAX小一点点
    cin>>m>>n;
    while(n--)
    {
        int x,y,c;
        cin>>x>>y>>c;
        mp[x][y]=c+1;   
    }   
    dfs(1,1,0,false);
    if(ans==inf)
    cout<<-1;
    else
    cout<<ans;
}   

C.跳房子(待研究)

D.列队(待研究)

E.小凯的疑惑

不多说了真的是反向筛选题,你想的越多这个题你就有可能陷入奇怪的境地

至于公式的证明方法的简略说法(伪证命)

因为要拿两个硬币,且两个硬币互质,那么如果每个硬币都拿一个的话就是能购买ab的物品。此时可以拿b个a也可以拿a个b也可以一样都不拿所以就是ab-a-b(伪证明)

代码

#include <bits/stdc++.h>
using namespace std;
main()
{
    long long a,b;
    cin>>a>>b;
    cout<<a*b-a-b;
}

F.时间复杂度(待研究)

G.图书管理员

这个题可算比较简单一些了,也是我唯一比赛中除了签到题做出来的题。直接用string输入数据转换成整型升序排序,然后把每个要比较的数进行比较即可。

代码

#include <bits/stdc++.h>
using namespace std;
string st1[1110];
string st2[1110];
bool cmp(string a,string b)//排序的规则函数,直接把输入的string转换成int排序,因为string的字典序对于这种常数的排序来说并不是升序的
{
    stringstream s1,s2;
    s1<<a;int c;
    s1>>c;
    s2<<b;int d;
    s2>>d;
    return c<d;
}
main()
{
    int n,q;
    cin>>n>>q;
    for(int i=0;i<n;i++)
    cin>>st1[i];
    for(int i=0;i<q;i++)
    {
        int k;
        cin>>k>>st2[i];
    }
    sort(st1,st1+n,cmp);
    for(int k=0;k<q;k++)//每一个情况的枚举
    {
        int f;//判断用的变量
        for(int i=0;i<n;i++)//把原来的图书编号一一的与要查询的编号进行比较
        {
            f=1;
            for(int j=1;j<=min(st1[i].size(),st2[k].size());j++)//比较的规则
            {
                if(st1[i].size()-(st2[k].size()+1)+j<0)//如果比较过程中出现了负数的数组下标,为了防止RE直接break,进行下一个图书编号的比较
                break;
                if(st1[i][st1[i].size()-(st2[k].size()+1)+j]!=st2[k][j-1])//方法自己手算一下就行这里进行比较
                {
                    f=0;
                    break;
                }
            }
            if(f)//如果发现比较成功直接输出然后break
            {
                cout<<st1[i]<<endl;
                break;
            }
        }       
        if(!f)//如果一趟下来没有比较成功的输出-1
        cout<<"-1\n";
    }
}

转载于:https://www.cnblogs.com/baccano-acmer/p/9821125.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值