1 条题解
-
0
题意分析:
输入格式:输入包含四行,每行四个字符,表示冰箱门上16个把手的初始状态。“+”表示闭合,“−”表示打开。 目标:通过最少的操作次数,使所有把手都处于打开状态。 操作规则:每次操作可以选择一个位置[i, j],改变该位置的行[i]和列[j]的状态。例如,如果某个位置从“−”变为“+”,则该行和该列的所有位置都会从“−”变为“+”或从“+”变为“−”。 输出格式:第一行输出最小操作次数N,接下来N行每行输出一个操作,格式为“i j”,表示对第i行第j列进行一次操作。
解题思路:
暴力枚举法:
遍历所有可能的操作组合,计算每种组合所需的最小操作次数。 检查每种组合是否能够使所有把手都打开。 记录并返回满足条件的最小操作次数及对应的序列。 位运算优化:
将矩阵的状态表示为一个整数变量,其中每一位对应一个把手的状态(0表示关闭,1表示打开)。 使用位运算快速判断某次操作是否会导致目标状态的达成。 通过枚举所有可能的操作组合,找到最小操作次数。 深度优先搜索(DFS):
使用递归方式逐步尝试不同的操作组合。 在递归过程中记录当前状态,并剪枝以减少不必要的计算。 状态压缩:
将矩阵的状态压缩为一个整数变量,减少存储空间。 使用状态压缩结合位运算或DFS进行求解。
算法标签:
暴力枚举 位运算 深度优先搜索(DFS) 状态压缩
#include <iostream> using namespace std; bool map[4][4]={0}; bool flag=false; int step; int res[16][2]={0}; //judge whether to an end bool isOver() { int i,j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(map[i][j]==0) { return false; } } } return true; } void change(int row,int col) { int i; map[row][col]=!map[row][col]; for(i=0;i<4;i++) { map[row][i]=!map[row][i]; } for(i=0;i<4;i++) { map[i][col]=!map[i][col]; } } void dfs(int row,int col,int deep) { if(deep==step) { flag=isOver(); return; } if(flag || row==4) { return; } change(row,col); res[deep][0] = row; res[deep][1] = col; if(col<3) { dfs(row,col+1,deep+1); } else { dfs(row+1,0,deep+1); } change(row,col); if(col<3) { dfs(row,col+1,deep); } else { dfs(row+1,0,deep); } } //1:open,0:close int main() { char temp; int i,j; //initial for(i=0;i<4;i++) { for(j=0;j<4;j++) { cin>>temp; if('-'==temp) { map[i][j]=1; } } } //function for(step=1;step<=16;step++) { dfs(0,0,0); if(flag) { break; } } //result cout<<step<<endl; for(i=0;i<step-1;i++) { cout << res[i][0] + 1 << " " << res[i][1] + 1 << endl; } cout << res[step - 1][0] + 1 << " " << res[step - 1][1] + 1; //system("pause"); return 0; }
- 1
信息
- ID
- 1966
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者