POJ 3279 Fliptile
1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 #include<queue>
5 #include<map>
6 #include<vector>
7 #include<set>
8 #include<string>
9 #include<cmath>
10 #include<cstring>
11 using namespace std;
12 const int MAX_N=20;
13 const int MAX_M=20;
14 const int dy[5]={-1,0,0,0,1};
15 const int dx[5]={0,-1,0,1,0};
16 int M,N;
17 int title[MAX_M][MAX_N];
18 int opt[MAX_M][MAX_N];//最优解
19 int flip[MAX_M][MAX_N];//中间结果
20
21 //查询(x,y)的颜色
22 int get(int x,int y)
23 {
24 int c=title[x][y];//先直接查询c颜色
25 for(int d=0;d<5;d++)//再遍历上下左右反转后会影响c的颜色的格子
26 {
27 int x2=x+dx[d],y2=y+dy[d];
28 if(0<=x2&&x2<M&&0<=y2&&y2<N)
29 {
30 c+=flip[x2][y2];//加起来
31 }
32 }
33 return c%2;//1是黑色 0是白色
34 }
35 //第一行确定后最小操作次数
36 //不存在返回-1
37 int calc()
38 {
39 //第二行开始的反转方法
40 for(int i=1;i<M;i++)
41 {
42 for(int j=0;j<N;j++)
43 {
44 if(get(i-1,j)!=0)
45 {
46 flip[i][j]=1;// (i-1,j)黑色就转这个格子
47 }
48 }
49 }
50 //判断最后一行是否全白
51 for(int j=0;j<N;j++)
52 {
53 if(get(M-1,j)!=0)
54 return -1;
55 }
56 //统计反转次数
57 int res=0;
58 for(int i=0;i<N;i++)
59 {
60 for(int j=0;j<N;j++)
61 {
62 res+=flip[i][j];
63 }
64 }
65 return res;
66 }
67 void solve()
68 {
69 int res=-1;
70 //按字典序查找第一行所有可能性
71 for(int i=0;i<1<<N;i++)
72 {
73 memset(flip,0,sizeof(flip));
74 for(int j=0;j<N;j++)
75 {
76 flip[0][N-j-1]=i>>j&1;
77 }
78 int num=calc();
79 if(num>=0&&(res<0||res>num))
80 {
81 res=num;
82 memcpy(opt,flip,sizeof(flip));//储存最优解
83 }
84 }
85
86 if(res<0) //无解
87 {
88 printf("IMPOSSIBLE\n");
89 }
90 else
91 {
92 for(int i=0;i<M;i++)
93 {
94 for(int j=0;j<N;j++)
95 {
96 printf("%d%c",opt[i][j],j+1==N?'\n':' ');
97 }
98 }
99 }
100 }
101 int main()
102 {
103 scanf("%d%d",&M,&N);
104 for(int i=0;i<M;i++)
105 {
106 for(int j=0;j<N;j++)
107 {
108 scanf("%d",&title[i][j]);
109 }
110 }
111 solve();
112 return 0;
113 }
分类:
OJ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步