状压dp

若集合大小不超过N,集合中每个元素都是小于K的自然数,则我们可以把这个集合看作
一个N位K进制数,以一个【0,K^N-1】之间的十进制整数的形式作为DP状态的一维。

for(int i=0; i < (1<<n) ; i++) ;
//相当于枚举了所有的选与不选的情况

1.判断一个数字x二进制下第i位是不是等于1。
方法:if(((1<<(i−1))&x)>0) if(((1<<(i−1))&x)>0)
将1左移i-1位,相当于制造了一个只有第i位上是1,其他位上都是0的二进制数。
然后与x做与运算,如果结果>0,说明x第i位上是1,反之则是0。

2.将一个数字x二进制下第i位更改成1。
方法:x=x|(1<<(i−1))x=x|(1<<(i−1))
证明方法与1类似,此处不再重复证明。

3.把一个数字二进制下最靠右的第一个1去掉。
方法:x=x&(x−1)x=x&(x−1)

题目描述
现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——按下了第i个按钮,
对于所有的灯都有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:

如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;
如果 -1,如果这盏灯是关的,那么把它打开,否则也不管;
如果 0,无论这灯是否开,都不管。

现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。

输入格式:
前两行两个数,n m
接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。
输出格式:
一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1

这题需要对状压及位运算有一定的了解:首先要判断某一位的灯是开的还是关的,才能进行修改。
具体解法是:对队首的某一状态,枚举每一个开关灯操作,记录到达这一新状态的步数
(也就是老状态 + 1),若是最终答案,输出,若不是,压入队列。
也就是说:我们把初始状态,用每个操作都试一遍,就产生了许多新的状态,再用所有操作一一
操作新状态,就又产生了新的新状态,我们逐一尝试,直到有目标状态为止,这可以通过BFS实现。
所以现在知道为什么状压比较暴力了吧。


#include<iostream>
#include<vector>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const int maxn = 2048;
int num,m,numd;
struct Node{
    int dp,step;
    };
int vis[maxn];
int map[maxn][maxn];
void BFS(int n){
    queue<Node>Q;
    Node fir;fir.step = 0,fir.dp = n;//初始状态入队,使灯的值都为一,
    Q.push(fir);
    while(!Q.empty()){//BFS
        Node u = Q.front();
        Q.pop();
        int pre = u.dp;
        for(int i = 1;i <= m;i++){//枚举每个操作
            int now = pre;
            for(int j = 1;j <= num;j++){
                if(map[i][j] == 1){
                    if( (1 << (j - 1)) & now){
                        now = now ^ (1 << (j - 1));//对状态进行操作
                        }
                    }
                else if(map[i][j] == -1){
                    now = ( (1 << (j - 1) ) | now);//对状态进行操作
                    }
                }
            fir.dp = now,fir.step = u.step + 1;//记录步数
            if(vis[now] == true){
                continue;
                }
            if(fir.dp == 0){//达到目标状态,都为零时为全灭
                vis[0] = true;//相当于一个标记flag
                cout<<fir.step<<endl;//输出
                return ;//退出函数
                }
            Q.push(fir);//新状态入队
            vis[now] = true;//表示这个状态操作过了(以后在有这个状态就不用试了)
            }
        }
    }
int main(){
    num = RD();m = RD();
    int n = (1 << (num)) - 1;
    for(int i = 1;i <= m;i++){
        for(int j = 1;j <= num;j++){
            map[i][j] = RD();
            }
        }
    BFS(n);
    if(vis[0] == false)
        cout<<-1<<endl;
    return 0;
    }

内容概要:本文档详细介绍了一个基于MATLAB实现的跨尺度注意力机制(CSA)结合Transformer编码器的多变量时间序列预测项目。项目旨在精准捕捉多尺度时间序列特征,提升多变量时间序列的预测性能,降低模型计算复杂度与训练时间,增强模型的解释性和可视化能力。通过跨尺度注意力机制,模型可以同时捕获局部细节和全局趋势,显著提升预测精度和泛化能力。文档还探讨了项目面临的挑战,如多尺度特征融合、多变量复杂依赖关系、计算资源瓶颈等问题,并提出了相应的解决方案。此外,项目模型架构包括跨尺度注意力机制模块、Transformer编码器层和输出预测层,文档最后提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,尤其是熟悉MATLAB和深度学习的科研人员、工程师和研究生。 使用场景及目标:①需要处理多变量、多尺度时间序列数据的研究和应用场景,如金融市场分析、气象预测、工业设备监控、交通流量预测等;②希望深入了解跨尺度注意力机制和Transformer编码器在时间序列预测中的应用;③希望通过MATLAB实现高效的多变量时间序列预测模型,提升预测精度和模型解释性。 其他说明:此项目不仅提供了一种新的技术路径来处理复杂的时间序列数据,还推动了多领域多变量时间序列应用的创新。文档中的代码示例和详细的模型描述有助于读者快速理解和复现该项目,促进学术和技术交流。建议读者在实践中结合自己的数据集进行调试和优化,以达到最佳的预测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值