JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
2017-11-07 17:18
501 查看
题目大意
有n个节点m条边,里面有一些不同种类钥匙。如果要通过一条边,需要有特定种类的钥匙(多把)。问最少要经过几条边从1走到n。数据范围
n≤5000,m≤6000,钥匙的种类k≤10。
题解
条件:①要求通过一条边有特定种类的钥匙。
②经过的边数最少。
特定的种类?时间复杂度肯定含有2^k,再套什么最短路算法比如spfa。
直接状压DP!!!
但是为什么时间超限?我蠢。
由于队列里已经记录了点x和具备钥匙的状态s,直接拿它去更新其他状态就好了,不必枚举冗余状态。
错误代码(TLE)
while(H<T){ H++; x=qu[H][0]; kk=qu[H][1]; for(i=head[x];i;i=edge[i].next){ fo(s,0,_2[k+1]-1){ v=s|a[x]; if((v|edge[i].val)!=v)continue; if(f[edge[i].to][v]>f[x][s]+1){ f[edge[i].to][v]=f[x][s]+1; if(!bz[edge[i].to][v]){ bz[edge[i].to][v]=1; qu[++T][0]=edge[i].to; qu[T][1]=v; } } } } bz[x][kk]=0; }
这个代码的缺点:
①枚举大量冗余状态。
②有松弛操作。
但是这道题目不需要松弛操作,因为第一次更新的解一定是状态的最优解。
所以bfs就好了。
总结
①对于spfa,如果已经有二进制的状态,就不必枚举代表意义相同的二进制状态。代码
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define N 5010 #define M 6010 #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; struct note{ int to,next,val; };note edge[M]; int head ,tot; int f [1030]; int i,j,k,ans,n,m,x,kk,temp; int u,v,H,T,s; long long sum,cnt; int _2[12]; int a ; int qu[N*3030][2]; void lb(int x,int y,int z){ edge[++tot].to=y; edge[tot].next=head[x]; edge[tot].val=z; head[x]=tot; } int main(){ freopen("room.in","r",stdin); freopen("room.out","w",stdout); _2[1]=1;fo(i,2,11)_2[i]=_2[i-1]*2; scanf("%d%d%d",&n,&m,&k); fo(i,1,n){ a[i]=0; fo(j,1,k){ scanf("%d",&x); a[i]+=_2[j]*x; } } fo(i,1,m){ scanf("%d%d",&u,&v); temp=0; fo(j,1,k){ scanf("%d",&x); temp+=_2[j]*x; } lb(u,v,temp); } memset(f,63,sizeof(f)); f[1][a[1]]=0; H=0,T=1; qu[1][0]=1; qu[1][1]=a[1]; while(H<T){ H++; x=qu[H][0];kk=qu[H][1]; for(i=head[x];i;i=edge[i].next){ if((kk|edge[i].val)!=kk)continue; v=kk|a[edge[i].to]; if(f[edge[i].to][v]==1061109567){ f[edge[i].to][v]=f[x][kk]+1; qu[++T][0]=edge[i].to; qu[T][1]=v; } } } ans=1061109567; fo(i,0,_2[k+1]-1)ans=min(ans,f [i]); if(ans==1061109567)printf("No Solution");else printf("%d",ans); return 0; }
相关文章推荐
- JZOJ5459. 【NOIP2017提高A组冲刺11.7】密室
- JZOJ 5459. 【NOIP2017提高A组冲刺11.7】密室
- JZOJ 5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- Jzoj5459【NOIP2017提高A组冲刺11.7】密室
- JZOJ 5458. 【NOIP2017提高A组冲刺11.7】质数
- JZOJ5460. 【NOIP2017提高A组冲刺11.7】士兵训练
- Jzoj5440 【NOIP2017提高A组冲刺11.1】背包
- JZOJ5440. 【NOIP2017提高A组冲刺11.1】背包
- JZOJ 5444. 【NOIP2017提高A组冲刺11.2】救赎
- JZOJ 5456. 【NOIP2017提高A组冲刺11.6】奇怪的队列
- JZOJ5458. 【NOIP2017提高A组冲刺11.7】质数
- 【JZOJ 5451】【NOIP2017提高A组冲刺11.4】Genocide
- JZOJ 5452. 【NOIP2017提高A组冲刺11.5】轰炸
- JZOJ5453. 【NOIP2017提高A组冲刺11.5】好路线
- JZOJ 5440. 【NOIP2017提高A组冲刺11.1】背包
- JZOJ 5466. 【NOIP2017提高A组冲刺11.9】玩游戏
- 【JZOJ 5445】【NOIP2017提高A组冲刺11.2】失格
- [JZOJ5445]【NOIP2017提高A组冲刺11.2】失格
- JZOJ 5445. 【NOIP2017提高A组冲刺11.2】失格
- JZOJ 5440. 【NOIP2017提高A组冲刺11.1】背包