zoukankan      html  css  js  c++  java
  • hdu1045 Fire Net---二进制枚举子集

    题目链接:
    http://acm.hdu.edu.cn/showproblem.php?pid=1045

    题目大意:

    给你一幅n*n的图,再给你一些点,这些点的上下左右不能再放其他点,除非有墙(‘X’)隔着,问最多可以放多少个这样的点。

    思路:

    由于n不大于4,最多16个点,想到可以二进制枚举子集,然后逐个判断每个子集的可行性。

     1 #include<iostream>
     2 #include<string>
     3 #include<vector>
     4 #include<cstdio>
     5 #include<cstring>
     6 #define FOR(i, a, b) for(int i = a; i < b; i++)
     7 using namespace std;
     8 int n, k;
     9 char a[10][10];
    10 int dir[4][2] = {1,0,0,1,-1,0,0,-1};
    11 bool judge(int x)
    12 {
    13     char b[10][10];
    14     int c[20], tot = 0;
    15     memcpy(b, a, sizeof(a));
    16     for(int i = 0; i < n * n; i++)
    17     {
    18         if(x & (1 << i))
    19         {
    20             int xx = i / n;
    21             int yy = i % n;
    22             if(b[xx][yy] == 'X')return false;//剪枝,如果子集覆盖了墙,直接返回假 
    23             b[xx][yy] = 'a';
    24             c[tot++] = i;
    25         }
    26     }
    27     for(int i = 0; i < tot; i++)//从每个点出发 
    28     {
    29         int x = c[i] / n;
    30         int y = c[i] % n;
    31         for(int i = 0; i < 4; i++)//四个方向遍历 
    32         {
    33             int xx = x + dir[i][0];
    34             int yy = y + dir[i][1];
    35             while(xx >= 0 && xx < n && yy >= 0 && yy < n)//控制边界 
    36             {
    37                 if(b[xx][yy] == 'X')break;//碰到墙跳出循环 
    38                 if(b[xx][yy] == 'a')return false;//碰到另一个'a'说明有误 
    39                 xx += dir[i][0];//继续往这方向遍历 
    40                 yy += dir[i][1];
    41             }
    42         }
    43     }
    44     return true;
    45 }
    46 int f(int x)//返回子集中的size 
    47 {
    48     int tot = 0;
    49     for(int i = 0; i < (n * n); i++)
    50     {
    51         if(x & (1 << i))tot++;
    52     }
    53     return tot;
    54 }
    55 int main()
    56 {    
    57     while(cin >> n && n)
    58     {
    59         int ans = 0;
    60         for(int i = 0; i < n; i++)cin >> a[i];
    61         for(int i = 0; i < (1 << (n * n)); i++)
    62         {
    63             if(judge(i))ans = max(ans, f(i));//更新最优解 
    64         }
    65         cout << ans << endl;
    66     }
    67     return 0;
    68 }

     听说可以用贪心或者二分图解决,以后学到这里再来更新

    NOIP普及组、提高组培训,有意可加微信fu19521308684
  • 相关阅读:
    js 数组详解(javascript array)
    CentOS 修改IP地址, DNS, 网关
    Leetcode 652.寻找重复的子树
    Leetcode 650.只有两个键的键盘
    Leetcode 649.Dota2参议院
    Leetcode 648.单词替换
    Leetcode 647.回文子串
    Leetcode 645.最长数对链
    Leetcode 643.子数组最大平均数I
    Leetcode 640.求解方程
  • 原文地址:https://www.cnblogs.com/fzl194/p/8674823.html
Copyright © 2011-2022 走看看