在POJ的first blood,一个dfs的解法,其中有很多巧妙的解法是值得学习的。
但它头文件居然不能#include<bits/stdc++.h>,好气哦
【题目】
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 47846 | Accepted: 20410 |
Description
- Choose any one of the 16 pieces.
- Flip the chosen piece and also all adjacent pieces to the left, to the right, to the top, and to the bottom of the chosen piece (if there are any).
![](https://i-blog.csdnimg.cn/blog_migrate/14b4b3ec0b5261bea3a5ad9f1313252c.jpeg)
bwbw
wwww
bbwb
bwwb
Here "b" denotes pieces lying their black side up and "w" denotes pieces lying their white side up. If we choose to flip the 1st piece from the 3rd row (this choice is shown at the picture), then the field will become:
bwbw
bwww
wwwb
wwwb
The goal of the game is to flip either all pieces white side up or all pieces black side up. You are to write a program that will search for the minimum number of rounds needed to achieve this goal.
Input
Output
Sample Input
bwwb bbwb bwwb bwww
Sample Output
4
4*4的格子翻硬币总共有多少种翻法,这是一个值得思考的问题。
假设只翻一个,则有16种翻法;翻两个的话,就是一个16选2的组合数问题了。以此类推,可以得出,总共可能出现的结果有2^16个结果,用dfs不会爆。。。
底下到了正经题解了。
首先写一个judge函数,判断是否所有的硬币向上面花色相同。。
int judge()
{
int x = a[0][0];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if (x!=a[i][j]) return 0;
return 1;
}
接着是一个flip函数,主要执行翻转操作。
void flip(int x,int y)
{
a[x][y] = !a[x][y];
if(x-1>=0) a[x-1][y] = !a[x-1][y];
if(x+1<4) a[x+1][y] = !a[x+1][y];
if(y-1>=0) a[x][y-1] = !a[x][y-1];
if(y+1<4) a[x][y+1] = !a[x][y+1];
}
(刚开始的时候漏了a[x][y] = !a[x][y],wa了半天)
底下到了最最重要的dfs,,
void dfs(int x,int y,int t)
{
if(judge()==1)
{
ans = min(t,ans);
return;
}
if(x>=4||y>=4) return;
int newx = (x+1)%4;
int newy = y+(x+1)/4;
dfs(newx,newy,t);
flip(x,y);
dfs(newx,newy,t+1);
flip(x,y);
return;
}
剽窃了某位大佬的思路,自己写数据模拟可得知,当newx加满到4后会回到1,此时newy会自动+1,思路十分巧妙。
每遇到一种情况,都有翻和不翻两种选择,因此dfs两次,当翻完以后,要再flip一次翻回来,此处就是回溯的思想了。
底下是完整代码。
#include<iostream>
#include<stdio.h>
using namespace std;
const int INF = 999999;
int a[10][10],ans;
char b[5][5];
int judge()
{
int x = a[0][0];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if (x!=a[i][j]) return 0;
return 1;
}
void flip(int x,int y)
{
a[x][y] = !a[x][y];
if(x-1>=0) a[x-1][y] = !a[x-1][y];
if(x+1<4) a[x+1][y] = !a[x+1][y];
if(y-1>=0) a[x][y-1] = !a[x][y-1];
if(y+1<4) a[x][y+1] = !a[x][y+1];
}
void dfs(int x,int y,int t)
{
if(judge()==1)
{
ans = min(t,ans);
return;
}
if(x>=4||y>=4) return;
int newx = (x+1)%4;
int newy = y+(x+1)/4;
dfs(newx,newy,t);
flip(x,y);
dfs(newx,newy,t+1);
flip(x,y);
return;
}
int main()
{
//freopen("d://test.txt","r",stdin);
ans = INF;
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
{
cin>>b[i][j];
if(b[i][j]=='b') a[i][j] = 0;
else if(b[i][j]=='w') a[i][j] = 1;
}
dfs(0,0,0);
if(ans==INF) cout<<"Impossible";
else cout<<ans;
return 0;
}
此题大致就是这样了,希望自己能坚持下来,acm有所作为。。