Mine Layer(2008 World Final C)数学问题+降维

本文介绍了一款名为MineLayer的游戏解题思路及实现方法。该游戏类似扫雷,玩家需根据线索找出地雷布局。文章提供了AC代码示例,通过一维和二维问题的转化,实现了对中间行地雷数量的最大值计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来自《挑战程序设计竞赛》

1.题目原文

Problem

MineLayer is a MineSweeper-like puzzle game played on an R by C grid. Each square in the grid either has one mine or no mines at all. A MineLayer puzzle consists of a grid of numbers, each of which indicates the total number of mines in all adjacent squares and in the square underneath. The numbers will thus range from zero to nine.

The objective of MineLayer is to figure out a layout of the mines in the grid that matches the given clues.

Below is a typical 3 by 4 grid. The original layout is on the left, and the puzzle on the right.

Since there may be many solutions, your task is to write a program that outputs the maximum possible number of mines in the middle row. The number of rows will always be odd, and there will always be at least one solution to the puzzle.

Input

The first line of input gives the number of cases, NN test cases follow.

The first line of each case contains two space-separated numbers: R, the number of rows, and C, the number of columns. R is always an odd integer. Each of the next R lines contains C space-separated numbers that denote the clues of that row.

Output

For each test case, output one line containing "Case #X: Y", where X is the 1-based case number, and Y is the maximum possible number of mines in the middle row of a grid that satisfies the given constraints.

Limits

1 ≤ N ≤ 50.
Each puzzle is guaranteed to have at least one solution.

Small dataset

R = 3 or R = 5.
3 ≤ C ≤ 5.

Large dataset

R is an odd number between 3 and 49, inclusive.
3 ≤ C ≤ 49.

Sample


Input 
 

Output 
 
2
3 3
2 2 1
3 4 3
2 3 2
3 4
1 2 1 1
2 3 3 2
2 2 2 1

Case #1: 1
Case #2: 1

2.解题思路

先从简化版的一维版问题考虑。每个格子有一个数字,但是不知道。只知道该格子和相邻格子的总和。
按照模3的余数分类讨论,即可解决。详情见代码。
接下来拓展到二维。只要先用前面的方法对各行求出全体之和,我们就可以得知每行及其上下行所含的地雷总数。然后再对各行的全体之和运用一维版问题的方法,就可以求出正中央那一行的地雷的个数了。
本题要求最大值,但是值是唯一的,这是本题设置的最大陷阱。

3.AC代码

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<utility>
#include<queue>
using namespace std;

#define MAX_RC 50
int R,C;
int A[MAX_RC][MAX_RC];

//计算长度为n的一维版问题的总和
int total(int *a,int n)
{
    int res=0;
    //按模3的余数讨论
    if(n%3==1||n%3==2){
        for(int i=0;i<n;i+=3){
            res+=a[i];
        }
    }
    else{
        for(int i=1;i<n;i+=3){
            res+=a[i];
        }
    }
    return res;
}

//计算长度为n的一维版问题正中央的数字
int center(int *a,int n)
{
    int res;
    //按模3的余数讨论
    if(n%3==1){
        res=total(a,n);
        for(int i=1;i<n/2;i+=3){
            res-=a[i];
            res-=a[n-1-i];
        }
    }
    else if(n%3==2){
        res=total(a,n);
        for(int i=0;i<n/2;i+=3){
            res-=a[i];
            res-=a[n-1-i];
        }
    }
    else{
        res=0;
        for(int i=0;i<n/2;i+=3){
            res+=a[i];
            res+=a[n-1-i];
        }
        res-=total(a,n);
    }
    return res;
}
int main()
{
    freopen("C-large-practice.in","r",stdin);
    freopen("C-large-practice.out","w",stdout);
    int t,kase=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&R,&C);
        for(int i=0;i<R;i++){
            for(int j=0;j<C;j++){
                scanf("%d",&A[i][j]);
            }
        }
        int row[MAX_RC];
        for(int i=0;i<R;i++){
            row[i]=total(A[i],C);
        }
        int ans=center(row,R);
        printf("Case #%d: %d\n",++kase,ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值