hdu 1045 贪心算法、DFS、枚举回溯&二分图

来源:互联网 发布:杜蕾斯大胆爱厚度 知乎 编辑:程序博客网 时间:2024/06/06 22:36

hdu 1045

题意:图1 表示的是正方形的区域(黑色表示墙壁、白色位置可以放城堡。),城堡所在的那一行和列不能放其他的城堡,因为城堡向四个方向发射子弹。墙壁可以挡住子弹的进攻,所以同一行或同一列只有城墙隔开的时候才能放两个城堡。图二展示的是图1的情况在最多能放的城堡数。图3是可行但不是最多的情况,图4和图5是错误的情况。![城堡图](http://img.blog.csdn.net/20170623160311506?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMTgwNjE5NA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)目的:求最多能放的城堡数。

法1 贪心算法

    ideal:贪心,每次找到能打到最少的位置放一个城堡,这样就可以尽可能的放很多。

代码解读:
1.计算每一行和每一列符号为’.’的位置能打到的位置,不能放城堡时,返回8。能返回城堡时,返回对应的打到的位置数。

int calNum(char a[4][4],int i,int j,int n){    int num = 0;    for(int s=j+1;s<n;s++){        if(a[i][s]=='.')num++;        else if(a[i][s]=='X')break;        else return 8;    }    for(int s=j-1;s>=0;s--){        if(a[i][s]=='.')num++;        else if(a[i][s]=='X')break;        else return 8;    }    for(int s=i+1;s<n;s++){        if(a[s][j]=='.')num++;        else if(a[s][j]=='X')break;        else return 8;    }    for(int s=i-1;s>=0;s--){        if(a[s][j]=='.')num++;        else if(a[s][j]=='X')break;        else return 8;    }    return num;}

2.对于计算产生的结果num进行遍历,找到最小的值。

int findmin(int num[],int n){    int min = 7;    int re = -1;    for(int i=0;i<n*n;i++){        if(num[i]<min){            re = i;            min = num[i];        }    }    return re;}
难点:求每个位置能打到的位置,因为有墙壁的阻隔作用,不能通过顺序遍历每一行和每一列来确定,只能从当前位置开始向两边遍历。遇到‘X’就停下来,但是遇到‘x’时,表示此行已经放了一个城堡,不能再放。改进地方:第一次求出每个‘.’位置放城堡能打到的位置数后,对其进行升序排序,就可以按照这个顺序进行城堡的放置。

DFS

   深搜:http://blog.csdn.net/pengwill97/article/details/54946853深搜的本质就是枚举:每一个格子里的所有情况都设置一下,如果满足条件就进行递归。如果不满足条件就对下一个元素进行深搜。   本人觉得深搜递归很多层,效率可能比较低。

枚举回溯

方法:将所有的情况列举出来,也就是有2的n*n中情况,对每种情况进行查看,最后得到结果。感觉效率太低。
int canset(int x){    memcpy(g,grid,sizeof(g));//重复前面的计算,每次的赋0都没有记录下来。    int res=0;    for(int i=0;i<n*n;i++){        if((x>>i)&1){//右移i表示找到当前位,&1可以认为是判断奇偶,那就是说当前的这个格是1的时候进行判断,而当前这一位是不放城堡的情况,就不用判断。            if(grid[i/n][i%n]!='.')return -1;            g[i/n][i%n]=0;            if(!check(i/n,i%n))return -1;            res++;        }    }    return res;}int main(){    ios::sync_with_stdio(0);    while(cin>>n,n){        for(int i=0;i<n;i++)            for(int j=0;j<n;j++){                cin>>grid[i][j];            }        int mx=0;        sm=(1<<(n*n))-1;        for(int i=1;i<=sm;i++){            mx=max(mx,canset(i));        }        cout<<mx<<endl;    }    return 0;}
原创粉丝点击