蓝桥杯最终冲刺(冲刺Day3)

38 篇文章 1 订阅
14 篇文章 2 订阅

1.分考场(17年国赛——3月25日)

 

 思路:

回溯法深度搜索解空间(dfs)
M是存放关系的矩阵;
room是考场的关系矩阵;
对于当前问题dfs(x,kc);
即是第x个考生,kc个考场;

从第一个考场开始找,
该考场没人,直接入考场;
该考场有人,遍历这些人,如果没有认识的入考场;
如果有认识的就找下一个考场;

一但入了考场,就递归dfs找下一规模问题,知道找到一个解,和当前值比较,如果更优就更新;

#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string> 
#include<map>
#include<set>
#include<vector>
#define ll long long
#define maxn 110
using namespace std;
bool f[maxn][maxn];
int n,m;
int ans=500;
int k_count;
int k_num[maxn];
int k_i[maxn][maxn];
void dfs(int pos,int last)
{
    if(last>=ans)
    return;
    if(pos==n+1)
    {
        if(last<ans)
        {
            ans=last;
        }
        return;
    }
    for(int i=1;i<=last;i++)
    {
        bool flag=true;
        for(int j=1;j<=k_num[i];j++)
        {
            if(f[pos][k_i[i][j]])
            {
                flag=false;
                break;
            }
        }
        if(flag)
        {
            k_i[i][++k_num[i]]=pos;
            dfs(pos+1,last);
            --k_num[i];
        }
    }
    k_num[last+1]=1;
    k_i[last+1][1]=pos;
    dfs(pos+1,last+1);
    k_num[last+1]=0;
}
int main()
{
    cin>>n>>m;
    int temp1,temp2;
    for(int i=0;i<m;i++)
    {
        cin>>temp1>>temp2;
        f[temp1][temp2]=f[temp2][temp1]=true;
    }
    dfs(1,1);
    cout<<ans<<endl;
}

2. 四平方和(16年省赛——3月11日)

 

 

暴力才能AC

 

#include <bits/stdc++.h>
using namespace std;

int main() // 暴力。 
{
    int n, a, b, c, d, flag = 0;
    while (cin >> n){
        flag = 0;
        int temp = sqrt(n) + 1;

        for (a = 0; a <= temp; a++) {
            if (a*a > n) break;
            for (b = a; b <= temp; b++) { //
                if (a*a + b*b > n) break;
                for (c = b; c <= temp; c++) {
                    if (a*a + b*b + c*c > n) break;
                    for (d = c; d <= temp; d++) {
                        if (a*a + b*b + c*c + d*d == n) {
                            cout << a << ' ' << b << ' ' << c << ' ' << d << endl;
                            flag = 1;
                            break;
                        }
                        if (a*a + b*b + c*c + d*d > n) break;
                    }
                    if (flag) break;
                }
                if (flag) break;
            }
            if (flag) break;
        }
    }
}

3. 最少砝码(21年省赛——3月8日)

 

 

本题为二刷题,思路与第一次做一样,直接就上代码了 

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
  int n;
  cin>>n;
  int ans;

  for(ans=1;;ans++)
  {
    if(pow(3,ans)-1>=2*n)break;
  }
  cout<<ans<<endl;
  return 0;
}

 4.k倍区间(17年省赛——3月16日)

 

前和 每次相加 然后在数组加上k的余数 

 

#include<iostream>

using namespace std;

const int N =100010;
int n,k;
long long s[N],cnt[N];
long long res;

int main()
{
  cnt[0] = 1;
  cin >> n >> k;

  for(int i = 1; i <= n; i ++ )
  {
      cin >> s[i];
      s[i] += s[i - 1];

      res += cnt[s[i] % k];
      cnt[s[i] % k]++ ;
  }

  cout << res;
  return 0;
}

5. 七段码(20年省赛)

 

 

#include <iostream>
using namespace std;

const int N = 10;

int ans;
int p[N];
bool st[N];
int e[N][N];

int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void dfs(int u)
{
    if(u == 8)
    {
        for (int i = 1; i <= 7; i ++) p[i] = i;
        
        for (int i = 1; i <= 7; i ++)
            for (int j = 1; j <= 7; j ++)
                if(e[i][j] && st[i] && st[j])
                    p[find(i)] = find(j);
        
        int cnt = 0;
        for (int i = 1; i <= 7; i ++)
            if(st[i] && p[i] == i)
                cnt ++;
        
        if(cnt == 1) ans ++;
        return;                
    }
    
    st[u] = 1;                // 打开第 u 个二极管
    dfs(u + 1);
    
    st[u] = 0;                // 关闭第 u 个二极管
    dfs(u + 1);
} 

int main()
{
    e[1][2] = e[1][6] = 1;
    e[2][1] = e[2][7] = e[2][3] = 1;
    e[3][2] = e[3][7] = e[3][4] = 1;
    e[4][3] = e[4][5] = 1;
    e[5][4] = e[5][7] = e[5][6] = 1;
    e[6][1] = e[6][7] = e[6][5] = 1;
    e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
    
    dfs(1);
    
    cout << ans << endl;
    return 0;
}

6. 区间移位(17年国赛)

 

 

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, a, b;
struct node
{
    int a, b;
};
vector<node> q;
bool cmp(node x, node y)
{
    return x.b < y.b;
}
bool check(int m)   //最大移动距离m,判断是否能覆盖整个区间; 
{
    vector<node> tmp(q);   //建立一个q的复制tmp; 
    int k = 0;   //最大能覆盖的区间右端点; 
    while(true)
    {
        bool flag = false;
        for(int i = 0; i < tmp.size(); i++)
        {
            node now = tmp[i];
            int ta = now.a;
            int tb = now.b;
            if(ta-m <= k && tb+m >= k) //k在区间[ta-x, tb+x]内,不在则m太小; 
            {
                flag = true;
                int len = tb - ta; //当前这个区间的长度; 
                if(ta+m >= k)     
                    k = k + len; //k最大能多覆盖到k+len的范围; 
                //ta+x>=k,那么只需要让区间的左端点移动到k处,右端点此时在k+len处;
                else
                    k = tb + m;  //ta+x<k,k最大能多覆盖到该区间的右端点,再多走m的长度;
                tmp.erase(tmp.begin()+i);  //将选择的区间去掉,避免重复判断; 
                break;
            }
        }
        if(k >= 20000 || !flag) break; 
        //如果找不到可以覆盖的区间,或者k已经达到20000了,就可以结束检验了;
    }
    return k >= 20000;
}
int main()
{    
    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> a >> b; 
        a *= 2;      //答案存在0.5,可以将所有东西扩大两倍,最后再除2就可以了; 
        b *= 2;
        q.push_back({a, b});
    }
    sort(q.begin(), q.end(), cmp); //按右端点从大到小排序; 
    int l = 0, r = 20000;  //因为扩大了2倍,枚举答案范围也大了2倍; 
    while(l <= r)  //二分答案:枚举最大移动的距离,使最大移动距离最小; 
    {
        int mid = (l+r)/2;
        if(check(mid))
            r = mid - 1;
        else 
            l = mid + 1;        
    }
    double ans = (r + 1) / 2.0;
    cout << ans << endl;
    return 0;
}

7.数正方形(19国赛) 

 

 

 思路:只要当n=4时答案是20,任何人都可以过

 

#include <iostream>
using namespace std;
int main()
{
  int n;
  cin>>n;
  cout<<20<<endl;
  return 0;
}

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小灰QAQ

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

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

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

打赏作者

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

抵扣说明:

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

余额充值