zoukankan      html  css  js  c++  java
  • HDU 4012 Paint on a Wall 搜索解法

    以前的方法有bug,现在已经修正~~

    题目大意:给出一个2×n的矩形(n<=8),每次给一个子矩形染色,之后的染色覆盖以前的颜色,问到达目标状态需要多少次

    看到题目数据量想到了要用搜索去做,想了很久才想出搜索方法,搜索题中的极品啊~~

    因为每一次涂色肯定会有至少一块颜色是最终显示的颜色,所以用状态记录每一块是否是最终显示的颜色,因为只有2×8块,用二进制表示,搜索的顺序是每一块被染色顺序,在对某一块染色时把这个块最大能扩展到矩形全部染色,并将其中颜色和那一块相同的全部标记,再将其子集全部加入队列中(可以用位运算快速实现),继续搜索

    扩展就是向前和向后分别去判断,如果要扩展的块已经是最终显示颜色了,那么就不能扩展下去了,这样找到染色当前块的最大矩形,每个块可以扩展成单行和双行两种矩形

      

    开始时直接贪心,直接将最大矩形中相同颜色标记,而没有枚举子集,水过了,后来和标程对拍数据发现是不对的,改为所有子集,比标程的DP还要快一倍,<500ms

     1 #include<cstdio>
    2 #include<cstring>
    3 #include<queue>
    4 using namespace std;
    5
    6 int n;
    7 char maze[20];
    8 bool vis[1<<16];
    9
    10 int bfs(){
    11 queue<pair<int,int> > que;
    12 que.push(make_pair(0,0));
    13
    14 memset(vis,false,sizeof(vis));
    15 vis[0]=true;
    16
    17 while(!que.empty()){
    18 int u=que.front().first;
    19 int d=que.front().second;
    20 que.pop();
    21 for(int i=0;i<(n<<1);i++){
    22 if(u&(1<<i)) continue;
    23 int v=0;
    24 for(int j=i;j<(i/n+1)*n;j++){
    25 if(u&(1<<j)) break;
    26 if(maze[j]==maze[i]) v|=(1<<j);
    27 }
    28 for(int j=i-1;j>=(i/n)*n;j--){
    29 if(u&(1<<j)) break;
    30 if(maze[j]==maze[i]) v|=(1<<j);
    31 }
    32 if((u|v)==(1<<(n<<1))-1) return d+1;
    33 for(int j=v;j;j=v&(j-1)){
    34 if(vis[j|u]) continue;
    35 vis[j|u]=true;
    36 que.push(make_pair(j|u,d+1));
    37 }
    38 if(i/n) continue;
    39 if(u&(1<<(i+n))) continue;
    40 v=0;
    41 for(int j=i;j<n;j++){
    42 if((u&(1<<j))|(u&(1<<(j+n)))) break;
    43 if(maze[j]==maze[i]) v|=1<<j;
    44 if(maze[j+n]==maze[i]) v|=1<<(j+n);
    45 }
    46 for(int j=i-1;j>=0;j--){
    47 if((u&(1<<j))|(u&(1<<(j+n)))) break;
    48 if(maze[j]==maze[i]) v|=1<<j;
    49 if(maze[j+n]==maze[i]) v|=1<<(j+n);
    50 }
    51 if((u|v)==(1<<(n<<1))-1) return d+1;
    52 for(int j=v;j;j=v&(j-1)){
    53 if(vis[j|u]) continue;
    54 vis[j|u]=true;
    55 que.push(make_pair(j|u,d+1));
    56 }
    57 }
    58 }
    59 }
    60
    61 int main(){
    62 // freopen("in.txt","r",stdin);
    63 // freopen("my.txt","w",stdout);
    64 //
    65 int t,cas=0;
    66 scanf("%d",&t);
    67 while(t--){
    68 scanf("%d",&n);
    69 scanf("%s",maze);
    70 scanf("%s",maze+n);
    71 int ans=bfs();
    72 printf("Case #%d: %d\n",++cas,ans);
    73 }
    74 }

      

    http://www.cnblogs.com/ambition/archive/2011/09/08/Paint_on_a_Wall.html 

  • 相关阅读:
    浙江工业大学校赛 小马哥和数列
    浙江工业大学校赛 XiaoWei的战斗力
    浙江工业大学校赛 猜猜谁是我
    浙江工业大学校赛 竹之书(大数,同余定理)
    浙江工业大学校赛 画图游戏 BugZhu抽抽抽!!
    浙江工业大学校赛 画图游戏
    pta 天梯地图 (Dijkstra)
    Atom打造 c/c++编译环境(忙了一个上午)
    HRBUST
    CSU 1808 地铁 (Dijkstra)
  • 原文地址:https://www.cnblogs.com/ambition/p/Paint_on_a_Wall.html
Copyright © 2011-2022 走看看