状态压缩
d
p
\frak{dp}
dp的一个重点就在于状态。压缩状态,就是为了利用状态进行转移。
既然是转移那就一定有起点和终点,所以状压
d
p
\frak{dp}
dp经常可以看到最短路的形式。
这道题的状态转移可能成环,所以要用最短路。
转移作边。形式在代码里面给出来了。
p s . \frak{ps.} ps.边权为 1 \frak{1} 1实际上可以 b f s \frak{bfs} bfs最短路
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<queue>
#include<cctype>
using namespace std;
int Eff_Positive[105]={};
int Eff_Negative[105]={},N,M;
int dis[5000]={};
int vis[5000]={};
#define PII pair<int,int>
priority_queue<PII,vector<PII>,greater<PII> >Q;
void dijkstra(int S)
{
memset(dis,0x3f,sizeof(dis)); dis[S]=0; memset(vis,0,sizeof(vis));
Q.push(make_pair(0,S));
while(!Q.empty())
{
int x=Q.top().second; Q.pop(); vis[x]=1;
for(int v,i=1;i<=M;++i)
{
v=x&(Eff_Positive[i])|Eff_Negative[i];
if(dis[v]>dis[x]+1)
{
dis[v]=dis[x]+1;
if(!vis[v])vis[v]=1,Q.push(make_pair(dis[v],v));
}
}
}
}
int main()
{
scanf("%d%d",&N,&M);
for(int i=1;i<=M;++i)
{
for(int t,j=N;j>=1;--j)
{
scanf("%d",&t);
if(t<=0)Eff_Positive[i]|=1<<j-1;
if(t==-1)Eff_Negative[i]|=1<<j-1;
}
}
dijkstra((1<<N)-1);
if(!vis[0])
{
printf("-1");
return 0;
}
printf("%d",dis[0]);
return 0;
}