POJ_1000:翻转卡片

题目:

1000:翻转卡片

总时间限制:  3000ms 内存限制:  65536kB


描述:

现在有N*N张卡片,组成了一个N*N的矩阵。这些卡片或者正面放置或者反面放置。现在,Acer想对这些卡片做一些翻转操作,使得所有的牌在翻转之后都正面朝上。在每一次操作中,Acer只能对一个M*M的子矩阵里的所有卡片做一次正反面翻转,也即将这个M*M矩阵中正面放置的卡片变成反面朝上,反面放置的卡片变成正面朝上。Acer想知道最少通过几次操作能够实现他的目标。输入第一行,两个整数N和M。


接下来的N行里,每一行1个整数。如果这个整数位1,表示这张对应的卡片在初始状态下时正面放置的;否则这张卡片最初是反面放置的。

对于所有数据,0


输出一个整数,表示实现目标所需要的最小操作次数。如果不可能实现目标,请输出-1。


样例输入

4 2

1 1 0 0

0 0 1 1

1 1 1 1

0 0 0 0


样例输出

5


分析:

使用贪心和递归方法,从每一行开始对每个元素进行检查,如果是0(反面), 则对以该点作为 M * M的左上角进行反转,使得当前元素变为1

注意: M *M 已越界,并且还存在0元素,则判定为无法实现,输出-1


#include <stdio.h> #define MAX_NUM 1000 int cards[MAX_NUM][MAX_NUM]; int time = 0; int N, M; void reverse(int row) { if (row + M >N) { // 以row 行开始的,如果已不足M行,则检查剩下的row行开始,有没有存在还是反面的卡片 for (int i = row; i < N; i++) { for (int j = 0; j < N; j++) { if (cards[i][j] == 0) { //存在反面的卡片 time = -1; return; } } } return; } for (int j = 0; j < N; j ++) { if (cards[row][j] == 1) continue; // 开始为1的不处理,即正面 if (j+M > N) { // 如果存在cards[row][j] 并且, j + M 已经大于N, 即无法进行用M*M 矩阵覆盖 time = -1; return; } // 开始覆盖, 从 row-> row+M, j -> j+M time++; for (int k = row; k < row + M ; k++) { for(int p = j; p < j + M; p++) { cards[k][p] =!cards[k][p]; } } } reverse(row+1); } int main() { //freopen("input.txt", "r", stdin); scanf("%d %d", &N, &M); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { scanf("%d", &cards[i][j]); } } reverse(0); printf("%d", time); return 0; }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值