[NOIP1997 普及组] 棋盘问题

题目背景

NOIP1997 普及组第一题

题目描述

设有一个 N×M 方格的棋盘 (1≤N≤100,1≤M≤100)

求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。

例如:当 N=2,M=3 时:

image.png

正方形的个数有 8 个:即边长为 1 的正方形有 6 个;边长为 2 的正方形有 2 个。

长方形的个数有 10 个:

  • 2×1 的长方形有 4 个:

    image.png

  • 1×2 的长方形有 3 个:

    image.png

  • 3×1 的长方形有 2 个:

    image.png

  • 3×2 的长方形有 1 个:

    image.png

输入描述

输入格式

一行两个整数 N,M。

输出描述

输出格式

一行两个整数,表示正方形的个数与长方形的个数。

用例输入 1

2 3

用例输出 1

8 10

看到这里,相信大家已经有思路了,可能会觉得,直接算不接好了吗?但是你想想,长方形怎么求?
所以,我的思路就是,算出来正方形的和总共的,长方形就等于总共的减正方形

接下来我们挨个分析:
输入部分
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int N,M;
    cin>>N>>M;
}

正方形:

    int zheng=0;
    for (int k=1;k<=min(N,M);k++) zheng+=(N-k+1)*(M-k+1);

总共的:

    int total=0;
    for (int i=1;i<=N;i++)
    {
        for (int j=1;j<=M;j++)
        {
            total+=(N-i+1)*(M-j+1);
        }
    }

长方形(总共的-正方形):

int chang=total-zheng;


输出:

cout<<zheng<<" "<<chang<<endl;


完整AC代码:
 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int N,M;
    cin>>N>>M;
    int zheng=0;
    for (int k=1;k<=min(N,M);k++) zheng+=(N-k+1)*(M-k+1);
    int total=0;
    for (int i=1;i<=N;i++)
    {
        for (int j=1;j<=M;j++)
        {
            total+=(N-i+1)*(M-j+1);
        }
    }
    int chang=total-zheng;
    cout<<zheng<<" "<<chang<<endl;
}

听懂了就点个关注吧,谢谢

### NOIP 1997 普及组 第一题 题目与解法 #### 题目描述 棋盘问题要求在一个给定大小的棋盘上放置一定数量的皇后,使得这些皇后之间不会互相攻击。具体来说,在一个 \( n \times n \) 的国际象棋棋盘上放置 \( k \) 个皇后,使它们互不攻击,即任意两个皇后都不能处于同一行、同一列或同一条斜线上。 输入包含多组测试数据。每组测试数据占两行,第一行为整数 \( n(0<n<11) \),表示棋盘的边长;第二行为整数 \( k(0\leqslant k\leqslant n) \),表示要放皇后的数目[^1]。 对于每一组测试数据,输出所有可能的摆放方案的数量。如果不存在任何合法的摆放方式,则输出 `No Answer`。 #### 解决方法概述 该问题可以通过回溯算法来解决。核心思路是从左到右逐列尝试放置皇后,并利用辅助数组记录已经占用的行以及两条对角线的状态。每当成功找到一组满足条件的位置组合时就增加计数器。 以下是具体的实现代码: ```cpp #include <iostream> using namespace std; int main() { int boardSize, queenCount; while (cin >> boardSize >> queenCount && boardSize != 0 || queenCount != 0){ bool rowUsed[11] = {false}; // 行标记 bool diag1[(2 * 11)-1] = {false}; // 主对角线标记 bool diag2[(2 * 11)-1] = {false}; // 副对角线标记 int solutions = 0; void backtrack(int col); if (!backtrack(queenCount)){ cout << "No Answer\n"; } } return 0; } void backtrack(int col){ static int pos[11]; // 当前列位置 if(col == 0){ ++solutions; return true; }else{ for(int i=1;i<=boardSize;++i){ if(!rowUsed[i]){ const int d1=i-col+boardSize-1,d2=i+col-2; if(diag1[d1]==false&&diag2[d2]==false){ rowUsed[i]=true; diag1[d1]=true; diag2[d2]=true; --pos[col]; if(backtrack(col-1)) return true; ++pos[col]; rowUsed[i]=false; diag1[d1]=false; diag2[d2]=false; } } } return false; } } ``` 上述程序实现了基本的回溯框架并处理了边界情况。注意这里的 `backtrack()` 函数用于递归地探索每一个潜在解决方案,并通过布尔型数组跟踪哪些行列已经被占据或者受到威胁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值