第七届蓝桥杯大赛个人赛(软件类)决赛真题

1.一步之遥 (15’)

他的面前是两个按钮,分别写着“F”和“B”。


小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。


矿车上的动力已经不太足,黄色的警示灯在默默闪烁...
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。


请填写为了达成目标,最少需要操作的次数。


注意,需要提交的是一个整数,不要填写任何无关内容(比如:解释说明等)


题解思路: bfs,求最短路


answer = 97


#include<bits/stdc++.h>
using namespace std;
map<int,int>vis;
struct P
{
    int x,step;
    P(int x,int step):x(x),step(step){}
    P(){}
};
int bfs()
{
     queue<P>que;
     P next;
     que.push(P(0,0));
     while(!que.empty()) {
        P p = que.front();
        que.pop();
        if(p.x==1) return p.step;
        next=P(p.x+97,p.step+1);
        if(!vis[next.x]) {
            vis[next.x] = 1;
            que.push(next);
        }
        next=P(p.x-127,p.step+1);
        if(!vis[next.x]) {
            vis[next.x] = 1;
            que.push(next);
        }
     }
}
int main()
{
    int ans = bfs();
    cout<<ans<<endl;
    return 0;
}


2.凑平方数(35’)


把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721


再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等...


注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。


如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?


注意:需要提交的是一个整数,不要填写多余内容。


解题思路(dfs+剪枝)


这道题思路很简单就是数据量大了,主要题意就是说让你把一个数字串分割,然后每个小分组都是平方数。

这道题可以从结果来推,先把10位以内所有平方数算出来当然要用到大整数不然会溢出。然后对这600多个数进行全排列,在排列过程中当然还要减支。

减支1:几个分组合在一起的字符串不能超过10个

减支2:剩下可用长度比当前选择的字符串长度还小后面就不用看了,因为我们生成平方数从小到大生成的,后面的数肯定比当前的大(这个减支不必须只是会大大降低时间)

减支3:当前选的数不能和前面已经选的字符串有相同字符

answer = 300


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1111;
const ll inf = 9876543210;
struct P
{
    ll x;
    int len;
    int b[11];
    P(ll x,int len):x(x),len(len){}
    P(){}
}a[N];
set<int>s;
int ans ,n;
void print()
{
    for(int i=1;i<30;i++) printf("%d\n",a[i].x);
}
bool work(ll num)
{
    int len=0;
    set<int>ss;
    while(num) {
        ss.insert(num%10);
        num/=10;
        len++;
    }
    if(len==ss.size()) return true;
    return false;
}
void dfs(int id)
{
    int i,j;
    if(s.size()==10) {
        ans++;
        return;
    }
    for(i=id;i<=n;i++) {
        if(a[i].len+s.size()>10) break;
        for(j=1;j<=a[i].len;j++) {
            if(s.find(a[i].b[j])!=s.end()) break;
        }
        if(j>a[i].len) {
            for(j=1;j<=a[i].len;j++) s.insert(a[i].b[j]);
            dfs(i+1);
            for(j=1;j<=a[i].len;j++) s.erase(s.find(a[i].b[j]));
        }
    }
}
int main()
{
    ll i,num;
    int len,j;
    a[1]=P(0,1);
    a[1].b[1]=0;
    n=1;
    for(i=1;i*i<=inf;i++) {
        len=0;
        num=i*i;
        while(num) {
            len++;
            num/=10;
        }
        num=i*i;
        if(work(num)) {
            a[++n]=P(num,len);
            for(j=1;j<=len;j++) {
                a[n].b[j]=num%10;
                num/=10;
            }
        }
    }
    ans=0;
    dfs(1);
    cout<<ans<<endl;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值