Tyvj1998
来源:互联网 发布:肖申克的救赎影评知乎 编辑:程序博客网 时间:2024/06/16 08:52
题目链接
分析:
这道题是今天的任务,受到的金币+30的诱惑,我就选择了这道题
真的怎么也没想到这是一道最短路
每使用一个补丁,就会达到一个状态,同时会消耗一定的时间
我们可以把不同的状态抽象成一个个的点,
每个点可以向ta的后继节点继续前进
这就相当于提问从起点到终点,经过若干操作,达到目标时的最小花费
这就是一个最短路模型
其实这也可以像bfs一样进行,但是因为有不同的花费,
所以要把所有的路径都搜出来,
那还不如我们把能够遍历到的所有状态一层一层的连起来,
跑一个最短路(最后还是转到了最短路上)
那我们就来说一下怎么建图吧:
用二进制存补丁的全部信息
我在代码中用了一些很zz的数组名称:
you[N],mei[N],xiu[N],chu[N] //有,没有,修复,出现
you数组存储该补丁使用时需要出现的漏洞,需要的状态是1
mei数组存储该补丁使用时不能出现的漏洞,不能出现的状态是1
xiu数组存储使用该补丁时修复的补丁,
这里要注意下,为了方便之后的计算,能够修复的状态是0,不能修复的状态是1
chu数组存储使用该补丁会引发的漏洞,出现的状态是1
具体计算
判断状态k,是否符合补丁i的使用条件:
(k&you[i])==you[j]&&(k&mei[i])==0
&:只有同是1的时候,值才为1
使用后的状态计算:
k=k|chu[j];
k=k&xiu[j];
|:只要一个是1,就是1
初始状态为2^n-1,末状态为0
跑最短路就好了
tip
只要是位运算,多加括号不是坏事
最短路我在这里选择的是spfa,如果用dij好像需要堆优化
这里写代码片#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int N=102;const int M=40000;int n,m;int T[N],you[N],mei[N],xiu[N],chu[N]; //有,没有,修复,出现struct node{ int x,y,v,nxt;}; node way[M<<4];int st[M],tot=0,q[M],tou,wei,sta,dis[M];bool p[M];void add(int u,int w,int v){ tot++; way[tot].x=u;way[tot].y=w;way[tot].v=v;way[tot].nxt=st[u];st[u]=tot;}int spfa(int s,int t){ memset(dis,0x33,sizeof(dis)); memset(p,1,sizeof(p)); p[s]=0; dis[s]=0; tou=wei=0; q[++wei]=s; do { int r=q[++tou]; for (int i=st[r];i;i=way[i].nxt) if (way[i].v+dis[r]<dis[way[i].y]) { dis[way[i].y]=way[i].v+dis[r]; if (p[way[i].y]) { p[way[i].y]=0; q[++wei]=way[i].y; } } } while (tou<wei); if (dis[t]==0x33333333) return 0; else return dis[t];}void doit(){ int i,j; for (i=1;i<=sta;i++) for (j=1;j<=m;j++) { int k=i; if ((k&you[j])==you[j]&&(k&mei[j])==0) //&都是1 { k=k|chu[j]; //出现 k=k&xiu[j]; //xiu是反的,同1得1 add(i,k,T[j]); } } printf("%d",spfa(sta,0));}int main(){ scanf("%d%d",&n,&m); char s[20]; sta=(1<<n)-1; //2^n-1; 1表示有该漏洞 for (int i=1;i<=m;i++) { scanf("%d",&T[i]); scanf("%s",&s); int num1=0,num2=0; for (int j=0;j<n;j++) { num1<<=1; num2<<=1; if (s[j]=='+') num1++; if (s[j]=='-') num2++; //包含了Bi+中的所有错误, 而没有包含Bi-中的任何错误时 } you[i]=num1; mei[i]=num2; scanf("%s",&s); num1=0,num2=0; for (int j=0;j<n;j++) { num1<<=1; num2<<=1; if (s[j]=='+') num1++; if (s[j]=='-') num2++; //Fi-中的任何错误都不会在软件中出现,而软件将包含Fi+中的所有错误 } xiu[i]=sta-num2; chu[i]=num1; } doit(); return 0;}
阅读全文
0 0
- Tyvj1998
- 最小生成树之kruskal算法概念与实现
- 读书笔记-《字符串》
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛 E: Half-consecutive Numbers
- 51Nod
- servlet学习笔记-第一天
- Tyvj1998
- iOS-round、ceil、floorf函数
- 数据库编码com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'sex' at row 1
- hdu 2577 How to Type 经典 二维 dp
- 整数转化为罗马数
- (main函数)
- python设计模式之访问者模式
- 51Nod
- Two Sum