蓝桥杯真题1

文章目录

    • 1.完全日期
    • 2.四平方和
    • 3.纸牌三角形
    • 4.直线
    • 5.路径
    • 6.砝码称重
    • 7.七段码


1.完全日期

蓝桥杯真题1_第1张图片

count=0
for i in range(2001,2022):
    for j in range(1,13):
        if j==4 or j==6 or j==9 or j==11:
            n=31
        elif j==2:
            n=29
        else:
            n=32
        for k in range(1,n):
            sum=0
            for a in str(i):
                sum=sum+int(a)
            for b in str(j):
                sum=sum+int(b)
            for c in str(k):
                sum=sum+int(c)
            if sum==9 or sum==16 or sum==25:
                count=count+1
print(count)

需要注意的是此代码没有考虑闰年的情况,在01年到21年中,一共有5个闰年,分别是2004,2008,2012,2016,2020,计算之后会发现,多加的那五天都不是完全日期。

2.四平方和

蓝桥杯真题1_第2张图片

#include
#include
using namespace std;
int n;

int main()
{
    cin>>n;
    int t=sqrt(n);
    double d;
    for(int a=0; a<t; a++)
    {
        for(int b=a; b<t; b++)
        {
            for(int c=b; c<t; c++)
            {
                d=sqrt(n-a*a-b*b-c*c);
                if(d==int(d)) //恰好减完
                {
                    cout<<a<<" "<<b<<" "<<c<<" "<<d;
                    return 0;
                }
            }
        }
    }
    return 0;
}

3.纸牌三角形

题意:
A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形(A按1计算)。要求每个边的和相等。
下图就是一种排法。

    A
   9 6
  4   8
 3 7 5 2

这样的排法可能会有很多。如果考虑旋转、镜像后相同的算同一种,一共有多少种不同的排法呢?请你计算并提交该数字。
注意:需要提交的是一个整数,不要提交任何多余内容。

#include
using namespace std;

int ans;
int arr[10];
int st[10];

void dfs(int len)
{
    if(len==9)
    {
        if(arr[0]+arr[1]+arr[2]+arr[3]==arr[3]+arr[4]+arr[5]+arr[6]&&arr[3]+arr[4]+arr[5]+arr[6]==arr[6]+arr[7]+arr[8]+arr[0])
        {
            ans++;
        }
        return;
    }
    for(int i=1; i<=9; i++)
    {
        if(!st[i])
        {
            arr[len]=i;
            st[i]=1;
            dfs(len+1);
            st[i]=0;
        }
    }
}

int main()
{
    dfs(0);
    cout<<ans/6<<endl;//去掉对称和旋转之后重复的
    return 0;
}

4.直线

蓝桥杯真题1_第3张图片
两点式:

蓝桥杯真题1_第4张图片

#include
#include
#include
#include
using namespace std;

struct Node
{
    int x;
    int y;
}node[450];

vector<int> v;
set<vector<int>> q;

int main()
{
    int cnt=0;
    for(int i=0;i<20;i++)//存
    {
        for(int j=0;j<21;j++)
        {
            node[cnt].x=i;
            node[cnt++].y=j;
        }
    }
    for(int i=0;i<cnt;i++)//遍历
    {
        for(int j=i;j<cnt;j++)
        {
            if(node[i].x==node[j].x&&node[i].y==node[j].y) continue;
            int a=node[j].y-node[i].y;
            int b=node[j].x-node[i].x;
            int c=node[i].x*node[j].y-node[i].y*node[j].x;
            int gcd=__gcd(a,__gcd(b,c));
            v.push_back(a/gcd);
            v.push_back(b/gcd);
            v.push_back(c/gcd);
            q.insert(v);
            v.clear();
        }
    }
    cout<<q.size()<<endl;
    return 0;
}

5.路径

蓝桥杯真题1_第5张图片
floyd:

#include
#include
using namespace std;

const int INF=1e9;
int d[2022][2022];

void floyd()
{
    for(int k=1;k<=2021;k++)
    {
        for(int i=1;i<=2021;i++)
        {
            for(int j=1;j<=2021;j++)
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        }
    }
}

int main()
{
    for(int i=1;i<=2021;i++)
    {
        for(int j=1;j<=2021;j++)
        {
            if(abs(i-j)<=21)
            {
                d[i][j]=i*j/__gcd(i,j);
            }
            else d[i][j]=INF;
        }
    }
    floyd();
    cout<<d[1][2021]<<endl;
    return 0;
}

蓝桥杯真题1_第6张图片
dijkstra:

#include
#include
#include
#include
using namespace std;

int g[2030][2030];
int dist[2030];
int st[2030];

int d()
{
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    for(int i=0;i<2021;i++)
    {
        int t=-1;
        for(int j=1;j<=2021;j++)
        {
            if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
        }
        st[t]=1;
        for(int j=1;j<=2021;j++)
        {
            dist[j]=min(dist[j],dist[t]+g[t][j]);
        }
    }
    if(dist[2021]==0x3f3f3f3f) return -1;
    else return dist[2021];
}

int main()
{
    memset(g,0x3f,sizeof g);
    for(int i=1;i<=2021;i++)
    {
    	for(int j=1;j<=2021;j++)
    	{
    		if(abs(i-j)<=21)
    		{
    			g[i][j]=i*j/__gcd(i,j);
    			g[j][i]=g[i][j];
    		}
    	}
    }
    printf("%d",d());
    return 0;
}

6.砝码称重

蓝桥杯真题1_第7张图片

dp法:

#include
using namespace std;

const int M=200020,B=M/2;//B为偏移量,因为数组下标不能为负数
int n,m;
int w[110];
bool f[110][M];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>w[i];
        m+=w[i];
    }
    f[0][B]=true;//初始化,当一个也不选时,这种情况成立
    for(int i=1;i<=n;i++)
    {
        for(int j=-m;j<=m;j++)
        {
            f[i][j+B]=f[i-1][j+B];//不选时,可以直接从i-1过渡到i
            if(j-w[i]>=-m) f[i][j+B]|=f[i-1][j-w[i]+B];//砝码放右边的情况
            if(j+w[i]<=m) f[i][j+B]|=f[i-1][j+w[i]+B];//砝码放左边的情况
        }
    }
    int cnt=0;
    for(int i=1;i<=m;i++)//从重量为1到m的区间内去选择
    {
        if(f[n][i+B]) cnt++;
    }
    cout<<cnt<<endl;
    return 0;
}

贴大佬做法:

#include
#include
using namespace std;
const int N = 105, M = 100005;
int g[N], n;
bitset<M> S;
int main(){
    scanf("%d", &n);
    for(int i = 0; i < n; i ++ ){
        scanf("%d", &g[i]);
    }
    S[0] = 1;
    for(int i = 0; i < n; i ++ ){
        S |= S << g[i];
    }
    for(int i = 0; i < n; i ++ ){
        S |= S >> g[i];
    }
    cout << S.count() - 1 << endl;
    return 0;
}

dfs(得一半分):

#include
using namespace std;

int n;
int w[100010];
int st[100010];
int cnt;

void dfs(int k,int m)
{
    if(k>n)
    {
        if(!st[m]&&m>0)
        {
            cnt++;
            st[m]=1;
        }
        return;
    }
    else
    {
        dfs(k+1,m);//不选
        dfs(k+1,m+w[k]);//右
        dfs(k+1,m-w[k]);//左
    }
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>w[i];
    dfs(0,0);
    cout<<cnt<<endl;
    return 0;
}

7.七段码

蓝桥杯真题1_第8张图片
法一:(数就完了)

统计不符合条件的
2个:15
3个:17
4个:7
5个:2
128-7-15-17-7-2=80

法二:(dfs+并查集)

#include
using namespace std;

const int N = 10;
int use[N], ans, e[N][N], p[N];

void init()
{
    /*
    	a b c d e f g
    	1 2 3 4 5 6 7
    */
    e[1][2] = e[1][6] = 1;
    e[2][1] = e[2][7] = e[2][3] = 1;
    e[3][2] = e[3][4] = e[3][7] = 1;
    e[4][3] = e[4][5] = 1;
    e[5][4] = e[5][6] = e[5][7] = 1;
    e[6][1] = e[6][5] = e[6][7] = 1;
    e[7][2] = e[7][3] = e[7][5] = e[7][6] = 1;
}

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

void dfs(int d)
{
    if(d > 7)
    {
        //并查集判是否在同一集合
        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] && use[i] && use[j]) //i和j相邻并且都亮着
                {
                    if(find(i)!=find(j)) p[find(i)]=find(j);//如果不在同一集合,合并
                }
            }
        }
        int k = 0;
        for(int i = 1; i <= 7; i++)
            if(use[i] && p[i] == i) k++;
        if(k == 1) ans++;//如果所有亮灯都属于同一个集合
        return;
    }
    use[d] = 1;//打开d这个灯,继续开关下一个灯
    dfs(d + 1);
    use[d] = 0;//关闭d这个灯,继续开关下一个灯
    dfs(d + 1);
}
int main()
{
    init();
    dfs(1);
    cout << ans;
}

你可能感兴趣的:(算法,算法)