蓝桥杯,省赛,三体攻击,承压计算,九宫幻方

文章讨论了两个编程题目:一个涉及三维数组的修改操作导致的负数出现情况,另一个是使用动态规划解决数塔取数问题,以及一个应用深度优先搜索的数独填充问题。
摘要由CSDN通过智能技术生成
/**     9-5 三体攻击 
**/
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int d[N];
int a,b,c,m,lat,rat,lbt,rbt,lct,rct,ht;
int getIdx(int i, int j, int k){
    return ((i-1)*b+(j-1))*c+(k-1)+1;
}
int main(){
    scanf("%d %d %d %d",&a,&b,&c,&m);
    for(int i=1;i<=a;i++){
        for(int j=1;j<=b;j++){
            for(int k=1;k<=c;k++){
                scanf("%d",&d[getIdx(i,j,k)]);
            }
        }
    }
    int key=0;
    for(int cnt=1;cnt<=m;cnt++){
        scanf("%d %d %d %d %d %d %d",&lat,&rat,&lbt,&rbt,&lct,&rct,&ht);
        if(key) continue;
        for(int i=lat;i<=rat;i++){
            for(int j=lbt;j<=rbt;j++){
                for(int k=lct;k<=rct;k++){
                    d[getIdx(i,j,k)]-=ht;
                    if(d[getIdx(i,j,k)]<0){
                        key = cnt;                        
                    }
                }
            }
        }
    }
    cout << key;
    return 0;
}

这段代码是一个三维数组的题目,题目描述为:有一个 a×b×c 的三维数组,每个位置上有一个数,现在有 m 次操作,每次操作会将一个长方体区域内的所有数减去一个数 ℎh,问在哪一次操作后,数组中是否存在负数。如果存在,输出这是第几次操作导致的,否则输出 00。

代码中的 getIdx 函数是为了将三维数组转化为一维数组,方便存储和访问。具体实现方法是将三维数组的每个位置映射到一维数组中,映射的方法为 (i−1)×b×c+(j−1)×c+k,其中 i,j,k 分别为三维数组中的三个下标。

代码中的 key 变量用于记录是否存在负数,如果存在,则将 key 赋值为当前操作的次数 cnt,并且在后面的操作中不再执行,直接跳过。

最后输出 key 即可。

承压计算

#include <bits/stdc++.h>
using namespace std;
const int N = 31;
double f[N][N];
double a[N][N] = {{0},{
0,7},{
0,5,8},{
0,7,8,8},{
0,9,2,7,2},{
0,8,1,4,9,1},{
0,8,1,8,8,4,1},{
0,7,9,6,1,4,5,4},{
0,5,6,5,5,6,9,5,6},{
0,5,5,4,7,9,3,5,5,1},{
0,7,5,7,9,7,4,7,3,3,1},{
0,4,6,4,5,5,8,8,3,2,4,3},{
0,1,1,3,3,1,6,6,5,5,4,4,2},{
0,9,9,9,2,1,9,1,9,2,9,5,7,9},{
0,4,3,3,7,7,9,3,6,1,3,8,8,3,7},{
0,3,6,8,1,5,3,9,5,8,3,8,1,8,3,3},{
0,8,3,2,3,3,5,5,8,5,4,2,8,6,7,6,9},{
0,8,1,8,1,8,4,6,2,2,1,7,9,4,2,3,3,4},{
0,2,8,4,2,2,9,9,2,8,3,4,9,6,3,9,4,6,9},{
0,7,9,7,4,9,7,6,6,2,8,9,4,1,8,1,7,2,1,6},{
0,9,2,8,6,4,2,7,9,5,4,1,2,5,1,7,3,9,8,3,3},{
0,5,2,1,6,7,9,3,2,8,9,5,5,6,6,6,2,1,8,7,9,9},{
0,6,7,1,8,8,7,5,3,6,5,4,7,3,4,6,7,8,1,3,2,7,4},{
0,2,2,6,3,5,3,4,9,2,4,5,7,6,6,3,2,7,2,4,8,5,5,4},{
0,7,4,4,5,8,3,3,8,1,8,6,3,2,1,6,2,6,4,6,3,8,2,9,6},{
0,1,2,4,1,3,3,5,3,4,9,6,3,8,6,5,9,1,5,3,2,6,8,8,5,3},{
0,2,2,7,9,3,3,2,8,6,9,8,4,4,9,5,8,2,6,3,4,8,4,9,3,8,8},{
0,7,7,7,9,7,5,2,7,9,2,5,1,9,2,6,5,3,9,3,5,7,3,5,4,2,8,9},{
0,7,7,6,6,8,7,5,5,8,2,4,7,7,4,7,2,6,9,2,1,8,2,9,8,5,7,3,6},{
0,5,9,4,5,5,7,5,5,6,3,5,3,9,5,8,9,5,4,1,2,6,1,4,3,5,3,2,4,1}};
int main(){
    for(int i = 1; i <= 29; i ++)
    {
        for(int j = 1; j <= i;j ++)
        { 
            double t = a[i][j] * 1.0 / 2;
            a[i + 1][j] += t;
            a[i + 1][j + 1] += t; 
        } 
    }
    double mi = 0x3f3f3f, ma = 0;
    for(int i = 1 ; i <= 30 ; i ++)
    {
        mi = min(a[30][i] , mi);
        ma = max(ma , a[30][i]);
    } 
    long long p = ma * (2086458231 * 1.0 / mi);
    cout << p << endl;
    return 0;
}

这段代码实现了一个数塔取数问题,通过动态规划的思想,从上往下逐层计算,得到最终的结果。其中,a数组存储了数塔中的数据,f数组存储了每个位置的最大值。具体实现过程如下:

1.首先,我们需要将数塔中的数据存储到数组a中。

2.然后,我们从第二层开始,逐层计算每个位置的最大值。对于第i层第j个位置,它的最大值为a[i][j]加上它上一层的左右两个位置的最大值中的较大值,即f[i][j] = a[i][j] + max(f[i-1][j-1],f[i-1][j])。

3.最后,我们遍历最后一层的所有位置,找到其中的最大值和最小值,然后通过一个公式计算出它们的比值,将这个比值乘以一个大质数,得到最终的结果。

代码实现比较简单,主要是对动态规划的思想的应用。

#include<bits/stdc++.h>
using namespace std;
int vis[10],a[5][5],ans[5][5];
int n,cnt;
pair<int ,int>p[10];
bool check(){
    int sum=a[1][1]+a[2][2]+a[3][3];
    if(sum!=a[1][3]+a[2][2]+a[3][1]) return false;
    for(int i=1;i<=3;i++){
    int tmp1=0,tmp2=0;
    for(int j=1;j<=3;j++)tmp1+=a[i][j],tmp2+=a[j][i];//行和列的和相等 
    if(tmp1!=sum||tmp2!=sum) return false;
    }
    return true;
} 
void dfs(int now){
    if(now>n){
        if(check()){
            cnt++;
            for(int i=1;i<=3;i++)
                for(int j=1;j<=3;j++)
                    ans[i][j]=a[i][j];
        }
        return;
    }
    int x=p[now].first,y=p[now].second;
    for(int k=1;k<=9;k++)
    {
        if(vis[k])continue;
        a[x][y]=k;
        vis[k]=1;
        dfs(now+1);
        a[x][y]=0;
        vis[k]=0;
    }
}
int main()
{
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++){
            cin>>a[i][j];
            if(!a[i][j])p[++n]=make_pair(i,j);
            vis[a[i][j]]=1;    
        }
    dfs(1);
    if(cnt==1){
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
                cout<<ans[i][j]<<" \n"[j==3];
            }
    else cout<<"Too Many\n";
    return 0;
 }

主要思路是深度优先搜索。首先输入,然后找到所有空格的位置,用dfs枚举每个空格可以填的数字,如果填完之后满足的规则,就记录答案并输出。如果有多个解,输出"Too Many"。

其中check函数用来检查当前填的数字是否符合数独的规则,即每行、每列、每个九宫格内的数字都不能重复,且每行、每列、对角线上的数字之和相等。

vis数组用来标记数字是否已经被用过,a数组表示当前填的数,ans数组表示最终的答案。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值