![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 using namespace std; 7 int n; 8 vector<int> chosen; 9 void calc(int x) { 10 if (x==n+1) { 11 for (int i=0; i<chosen.size(); ++i) 12 printf("%d ", chosen[i]); 13 cout<<endl; 14 return; 15 } 16 calc(x+1); 17 chosen.push_back(x); 18 calc(x+1); 19 chosen.pop_back(); 20 } 21 int main() { 22 cin>>n; 23 calc(1); 24 return 0; 25 }
在前面的基础上加入以下代码即可:
if (chosen.size()>m||chosen.size()+(n-x+1)<m) return;
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 using namespace std; 7 int n, m; 8 vector<int> chosen; 9 void calc(int x) { 10 if (chosen.size()>m||chosen.size()+(n-x+1)<m) 11 return; 12 if (x==n+1) { 13 for (int i=0; i<chosen.size(); ++i) 14 printf("%d ", chosen[i]); 15 cout<<endl; 16 return; 17 } 18 chosen.push_back(x); 19 calc(x+1); 20 chosen.pop_back(); 21 calc(x+1); 22 } 23 int main() { 24 cin>>n>>m; 25 calc(1); 26 return 0; 27 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 using namespace std; 7 int n; 8 int order[20]; 9 int chosen[20]; 10 void calc(int k) { 11 if (k==n+1) { 12 for (int i=1; i<=n; ++i) 13 printf("%d ", order[i]); 14 puts(""); 15 return; 16 } 17 for (int i=1; i<=n; ++i) { 18 if (chosen[i]) continue; 19 order[k]=i; 20 chosen[i]=1; 21 calc(k+1); 22 order[k]=0; 23 chosen[i]=0; 24 } 25 } 26 int main() { 27 cin>>n; 28 calc(1); 29 return 0; 30 }
容易发现3个性质:
1.每个位置最多点击一次
2.固定了第一行,满足题意的点击方案只有一种,如第i行已被固定,第i位为1,则第i+1行该位置需要被点击
3.点击先后顺序不影响最终结果
所以用位运算枚举第一行的点击方案,再递推出2~5行的点击,最后判断第5行是否满足题意即可。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int g[10][10]; char nex[5][2]={{0,0},{0,-1},{-1,0},{1,0},{0,1}}; void turn(int x, int y) { for (int i=0; i<5; ++i) { int tx=x+nex[i][0]; int ty=y+nex[i][1]; if (tx>0&&tx<=5&&ty>0&&ty<=5) g[tx][ty]^=1; } } void print() { /*for (int i=1; i<=5; ++i) { for (int j=1; j<=5; ++j) printf("%1d", g[i][j]); printf("\n"); } puts("");*/ } int solve() { int ans=0x3f3f3f3f; for (int i=0; i<32; ++i) { int flag=1, tot=0; int tmp[10][10]; memcpy(tmp, g, sizeof(tmp)); for (int j=0; j<5; ++j) if ((i>>j)&1) //如果第j位为1,则第一排的第j位需要被按一下 { turn(1, j+1); tot++; print();/*printf("a\n");*/} for (int j=1; j<5; ++j) { for (int k=1; k<=5; ++k) if (g[j][k]==0) { turn(j+1, k); tot++; print();/*printf("b\n");*/} } for (int j=1; j<=5; ++j) if (g[5][j]==0) flag=0; memcpy(g, tmp, sizeof(g)); if (flag) ans=min(ans, tot); else continue; } if (ans>6) return -1; return ans; } int main() { //freopen("1.txt", "w", stdout); int T; scanf("%d", &T); while (T--) { for (int i=1; i<=5; ++i) for (int j=1; j<=5; ++j) scanf("%1d", &g[i][j]); printf("%d\n", solve()); } return 0; } /* 1 11101 11101 11110 11111 11111 */