• 洛谷 P2622 关灯问题II(状压DP入门题)


    传送门

    https://www.cnblogs.com/violet-acmer/p/9852294.html

    题解:

      相关变量解释:

     1 int n,m;
     2 int a[maxn][20];//a[i][j] : 第i个开关对第j个灯的效果。
     3 bool vis[R(10)];//vis[i] : 判断状态i是否被访问过
     4 struct Node
     5 {
     6     int status;//状态
     7     int minTimes;//来到当前状态按下开关的最小次数
     8     Node(int a=0,int b=0):status(a),minTimes(b){}
     9 };
    10 queue<Node >myqueue;//用队列中的状态去解锁其他为解锁(访问)过的状态,并能保证被解锁的状态的minTimes最小

      步骤:

      (1):将Node( (1<<n)+1,0 ) 加入队列,因为初始等全是亮的,对应到二进制就是n个1,并且需要 0 次按下开关。

      (2):从队头依次弹出元素,并用当前状态去解锁其他状态,并能保证被其解锁的状态的minTimes是最小的。

      (3):重复(2)过程,直到找到 0 状态或队列为空

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<queue>
     4 #include<cstring>
     5 using namespace std;
     6 #define mem(a,b) memset(a,b,sizeof(a))
     7 #define R(x) (1<<x)
     8 const int maxn=100+10;
     9 
    10 int n,m;
    11 int a[maxn][20];//a[i][j] : 第i个开关对第j个灯的效果。
    12 bool vis[R(10)];//vis[i] : 判断状态i是否被访问过
    13 struct Node
    14 {
    15     int status;//状态
    16     int minTimes;//来到当前状态按下开关的最小次数
    17     Node(int a=0,int b=0):status(a),minTimes(b){}
    18 };
    19 queue<Node >myqueue;//用队列中的状态去解锁其他为解锁(访问)过的状态,并能保证被解锁的状态的minTimes最小
    20 
    21 int nextStatus(int nowStatus,int i)
    22 {
    23     int x=nowStatus;
    24     for(int j=1;j <= n;++j)//从右往左一一对应
    25     {
    26         if(a[i][j] == 1 && (x>>(j-1)&1))//一定要注意判断x的第j为是否为1
    27             x ^= (1<<(j-1));//^ : 相同为0,不同为1
    28         else if(a[i][j] == -1)
    29             x |= (1<<(j-1));
    30     }
    31     return x;
    32 }
    33 int updataQ(Node node)
    34 {
    35     for(int i=1;i <= m;++i)
    36     {
    37         int status=nextStatus(node.status,i);//找到当前状态node.status可以解锁的下一状态
    38         if(!vis[status])//如果被访问过,那么其minTimes肯定要小于当前的minTimes+1
    39             myqueue.push(Node(status,node.minTimes+1)),vis[status]=true;
    40         if(status == 0)//判断被解锁的状态是否为0状态
    41             return node.minTimes+1;
    42     }
    43     return 0;
    44 }
    45 int Solve()
    46 {
    47     mem(vis,false);
    48     while(!myqueue.empty())
    49         myqueue.pop();
    50     myqueue.push(Node(R(n)-1,0));//步骤(1)
    51     while(!myqueue.empty())//步骤(2)(3)
    52     {
    53         Node node=myqueue.front();
    54         myqueue.pop();
    55         int res=updataQ(node);//更新队列中的状态
    56         if(res != 0)//判断被解锁的状态是否有0状态,如果有,直接输出,一定是最小的按下次数
    57             return res;
    58     }
    59     return -1;
    60 }
    61 int main()
    62 {
    63     scanf("%d%d",&n,&m);
    64     for(int i=1;i <= m;++i)
    65         for(int j=n;j >= 1;--j)//j : n down 1 用意:与二进制的位数一一对应(从右往左)
    66             scanf("%d",a[i]+j);
    67     printf("%d
    ",Solve());
    68 }
    View Code
  • 相关阅读:
    scrapy 第一个案例(爬取腾讯招聘职位信息)
    scrapy 代码调试用 shell
    scrapy 命令行创建 启动 跟踪
    scrapy 手动编写模板
    scrapy安装
    爬虫之xpath用法
    爬虫之 beautifusoup4
    抓包工具fiddler
    12306登录爬虫 session版本
    Drainage Ditches(dinic)
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9997506.html
Copyright © 2020-2023  润新知