HDU2209+POJ3279 枚举+dfs

来源:互联网 发布:1024控台控制帕灯编程 编辑:程序博客网 时间:2024/06/06 04:50

传送门:HDU2209

传送门:POJ3279

说实话真不知道这两个题算不算搜索,只说枚举也不为过。因为核心思想就是枚举,然后剩下的部分就是检查了。

先说比较简单的HDU2209,下面给的链接讲解的挺明白的   点击打开链接   注意上一张的状态决定下一张是否翻转就好了,其他还比较好理解。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;char s[25],n[25];int book[25];int flag=0,ans=0,len;void dfs(int i,int cnt){if(i==len){for(int j=0;j<len;j++){if(n[j])return ;}flag=1;ans=min(ans,cnt);return ;}if(n[i-1]){n[i-1]=!n[i-1];n[i]=!n[i];n[i+1]=!n[i+1];dfs(i+1,cnt+1);}elsedfs(i+1,cnt);}int main(){while(~scanf("%s",s)){flag=0,ans=999;len=strlen(s);for(int i=0;i<len;i++)n[i]=s[i]-'0';dfs(1,0);//不翻第一张的时候for(int i=0;i<len;i++)n[i]=s[i]-'0';n[0]=!n[0];n[1]=!n[1];dfs(1,1);//翻转第一张以后if(!flag)printf("NO\n");elseprintf("%d\n",ans);}return 0;}

下面来说POJ3279,由一维变到二维瞬间就难了好多。。同样下附大神分析..

点击打开链接     点击打开链接    点击打开链接

一维枚举第一个的状态,二维自然就是枚举第一行的状态啦,第一行的状态确定以后,每块地翻不翻就由它上一行对应的地的状态来决定,如果是上一行对应的是1就翻转。注意这里判断翻转后某一格到底是1还是0的时候,要将它周围的四个格子的翻转次数以及它本身的翻转次数加起来,因为这五个格子的翻转都会引起它的状态的变化,如果和是奇数就代表是1。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;int n,m;int map[20][20];int flip[20][20],ans[20][20];int go[5][2]={0,0,0,1,1,0,0,-1,-1,0};int get(int r,int c)//判断某块地翻转以后的状态{int t=map[r][c];//先加上初状态,即输入的状态int tr,tc;for(int i=0;i<5;i++){tr=r+go[i][0];tc=c+go[i][1];if(tr>=0&&tc>=0&&tr<n&&tc<m){t+=flip[tr][tc];}}return t%2;}int solve(){for(int i=1;i<n;i++)//从第二行开始{for(int j=0;j<m;j++)if(get(i-1,j))//如果是同一列上一行对应的是1就翻转flip[i][j]++;}for(int i=0;i<m;i++)//判断最后一行的状态(是否全0){if(get(n-1,i))return 0;}int sum=0;for(int i=0;i<n;i++)//统计翻转次数for(int j=0;j<m;j++)sum+=flip[i][j];return sum;}int main(){while(~scanf("%d%d",&n,&m)){memset(ans,0,sizeof(ans));int min=99999999;for(int i=0;i<n;i++){for(int j=0;j<m;j++)scanf("%d",&map[i][j]);}for(int i=0;i<(1<<m);i++)//i代表第一行状态,从全0到全1.{memset(flip,0,sizeof(flip));for(int j=0;j<m;j++)flip[0][j]=i>>(m-j-1)&1;//这里的位运算要自行举例子理解了...int t=solve();if(t&&t<min)//判断是否要更新答案{min=t;memcpy(ans,flip,sizeof(flip));}}if(min==99999999)printf("IMPOSSIBLE\n");else{for(int i=0;i<n;i++){for(int j=0;j<m;j++)printf("%d ",ans[i][j]);putchar('\n');}}}return 0;}


0 0
原创粉丝点击