枚举问题总结

来源:互联网 发布:淘宝内衣哪些有买家秀 编辑:程序博客网 时间:2024/06/05 19:38

枚举

画家问题

注意无解的情况的判断

http://poj.org/problem?id=1681

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#define N 20using namespace std;int puzzle[N][N],press[N][N];int n;bool success;bool guess(){int r,c;for(r=1;r<n;r++){for(c=1;c<=n;c++){press[r+1][c]=(puzzle[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;}}//看最后一行是否全被染为黄色for(c=1;c<=n;c++){if( (press[n][c-1]+press[n][c+1]+press[n-1][c]+press[n][c])%2!=puzzle[n][c] )    return false;} return true;} void enumate(){//只需一次枚举第一行的状态    int c;    for(c=1;c<=n;c++)        press[1][c]=0;    while(guess()==false)    {    press[1][1]++;    c=1;    while(press[1][c]>1)    {    press[1][c]=0;    c++;    press[1][c]++;}//注意这里的处理 if(press[1][n+1]==1){//说明枚举了所有状态都没有成功    success=false;     break;}}return;} int main(){int t;scanf("%d",&t);while(t--){success=true;memset(press,0,sizeof(press));memset(puzzle,0,sizeof(puzzle));scanf("%d",&n);getchar();char buf[N];for(int i=1;i<=n;i++){gets(buf+1);for(int j=1;j<=n;j++){if(buf[j]=='w')    puzzle[i][j]=1;//1表示白色else    puzzle[i][j]=0; }}enumate();if(success){int cnt=0;for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)        if(press[i][j]==1)            cnt++;    printf("%d\n",cnt);}else    printf("inf\n");}return 0;}

拨钟问题:

依次枚举每种操作

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>using namespace std;/*每个移动可以操作次数为3次,就可以出现4种状态 因为时钟的状态为4个和熄灯问题类似,熄灯共两种状态,所以操作总共就1次 */int M[9][9]={1,1,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,1,1,0,1,1};int buf[9]; int ans[9];int main(){for(int i=0;i<9;i++){scanf("%d",&buf[i]);}int m1,m2,m3,m4,m5,m6,m7,m8,m9;//代表题目给的9种操作 ,0代表不操作,1,2,3代表操作1,2,3次 int i,cnt;int mins=50;for(m1=0;m1<=3;m1++){for(m2=0;m2<=3;m2++){for(m3=0;m3<=3;m3++){for(m4=0;m4<=3;m4++){for(m5=0;m5<=3;m5++){for(m6=0;m6<=3;m6++){for(m7=0;m7<=3;m7++){for(m8=0;m8<=3;m8++){for(m9=0;m9<=3;m9++){bool flag=true;for(i=0;i<9;i++){//代表ABCDEFGHI 9个时钟 0,1,2,3共4种状态 if((buf[i]+m1*M[0][i]+m2*M[1][i]+m3*M[2][i]+m4*M[3][i]+m5*M[4][i]+m6*M[5][i]+m7*M[6][i]+m8*M[7][i]+m9*M[8][i])%4!=0)    {    flag=false;    break;}}if(flag){cnt=m1+m2+m3+m4+m5+m6+m7+m8+m9;if(cnt<mins)    {    mins=cnt;    ans[0]=m1;    ans[1]=m2;    ans[2]=m3;    ans[3]=m4;    ans[4]=m5;    ans[5]=m6;    ans[6]=m7;    ans[7]=m8;    ans[8]=m9;}}}}}}}}}}}bool mark=false;for(int j=0;j<9;j++){while(ans[j]--){if(!mark)   printf("%d",j+1);else   printf(" %d",j+1);mark=true;}}printf("\n");return 0;}

恼人的青蛙

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<string>#include<algorithm>#define N 5005using namespace std;struct PLANT{int x,y;}plant[N];int r,c,n,dx,dy,px,py,steps,maxs=2;int myCompare(const void* ele1,const void* ele2){PLANT *p1,*p2;p1=(PLANT*)ele1;p2=(PLANT*)ele2;if((p1->x) == (p2->x))     return (p1->y-p2->y);//从小到大排序else    return (p1->x-p2->x); }int searchPath(PLANT p,int dx,int dy){PLANT tmp;int step;tmp.x=p.x+dx;tmp.y=p.y+dy;step=2;while(tmp.x<=r && tmp.x>=1 && tmp.y<=c && tmp.y>=1){//下一步在稻田内,但是又没被踩,说明该路径不是被踩路径 //否则,继续下一步 if(!bsearch(&tmp,plant,n,sizeof(PLANT),myCompare)){step=0;break;}tmp.x+=dx;tmp.y+=dy;step++; } return step;} int main(){bool flag=false;    scanf("%d%d",&r,&c);    scanf("%d",&n);    for(int i=0;i<n;i++)    {    scanf("%d%d",&plant[i].x,&plant[i].y); }qsort(plant,n,sizeof(PLANT),myCompare);//按行坐标从小到大排序 //依次枚举前两步,注意剪枝 for(int i=0;i<n-2;i++){for(int j=i+1;j<n-1;j++){dx=plant[j].x-plant[i].x;//dx一定 >=0 dy=plant[j].y-plant[i].y;//dy不一定 px=plant[i].x-dx;py=plant[i].y-dy;//点必须在稻田外才符合 if(px>=1 && px<=r && py>=1 && py<=c)    continue;if(plant[i].x+maxs*dx>r)    break;//如果第三个点在稻田外,那么不用往下列举了,接下来的dx肯定会越来越大py=plant[i].y+maxs*dy;if(py>c|| py<1){//如果y方向上只能满足第三个点在稻田外,那么必须依次列举,因为接下来的点有可能dy会更小 continue; } steps=searchPath(plant[j],dx,dy);if(steps>=maxs){    maxs=steps;    flag=true;}} }// if(flag)    printf("%d\n",maxs);else    printf("0\n");return 0;}



0 0
原创粉丝点击