随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

 一、题目描述:

  大陆上有 n 个村庄,m 条双向道路,p 种怪物,k 个铁匠,铁匠住在一些村庄里,他会给你打造他所能打造的所有剑。

  特定的剑可以对付特定的怪物,每条道路上都可能出现一些特定的怪物,每条道路有一个通过时间。

  现在要从 1 走到 n,初始的时候你没有剑,要求在经过一条道路的时候,对于任意一种出现在这条道路上的的怪物,你已经有相应的剑可以对付他。

  求从 1 走到 n 的最短时间(打造剑不需要时间)。如果不能到达 n ,输出 -1。1<=n<=200,0<=m<=3000,1<=p<=13,0<=k<=n 


 二、做题思路

  p这么小,果断状压存状态。设 dp[i][j] 表示走到第 i 个点状态为 j 的最短路,跑一遍 dij 就可以了。(看起来挺简单,实际上我还是写了很久qwq)


 三、完整代码:

复制代码
 1 #include<iostream>
 2 #include<cstring>
 3 #include<queue>
 4 #define N 210
 5 #define M 3010
 6 using namespace std;
 7 int n,m,p,k,u1,v1,w1,s1,t1,n1;
 8 int dis[N][(1<<13)+10],ab[N],vis[N][(1<<13)+10];
 9 struct EDEG{
10     int v,w,gs,nxt;
11 }e[M*2];
12 int head[N],cnt;
13 void add(int u,int v,int w,int gs)
14 {
15     e[++cnt].nxt=head[u];head[u]=cnt;
16     e[cnt].v=v;e[cnt].w=w;e[cnt].gs=gs;
17 }
18 struct node{
19     int val,status,dis;
20     bool operator < (const node &t)const{
21         return t.dis<dis;
22     }
23 };
24 priority_queue <node> q;
25 void dij(int s)
26 {
27     dis[1][0]=0;
28     q.push({1,0,0});
29     while(!q.empty())
30     {
31         node tt=q.top();q.pop();
32         int u=tt.val,d=tt.status;
33         if(vis[u][d])continue;vis[u][d]=1;
34         dis[u][d|ab[u]]=dis[u][d];d|=ab[u];
35         for(int i=head[u];i!=-1;i=e[i].nxt)
36             if((e[i].gs&d)==e[i].gs)
37                 if(dis[e[i].v][d]>dis[u][d]+e[i].w)
38                 {
39                     dis[e[i].v][d]=dis[u][d]+e[i].w;
40                     q.push({e[i].v,d,dis[e[i].v][d]});
41                 }
42     }
43 }
44 int main()
45 {
46     ios::sync_with_stdio(false);
47     cin.tie(0);cout.tie(0);
48     cin>>n>>m>>p>>k;
49     for(int i=1;i<=k;i++)
50     {
51         cin>>u1>>s1;
52         for(int j=1;j<=s1;j++)
53         {
54             cin>>v1;
55             ab[u1]|=(1<<(v1-1));
56         }
57     }
58     memset(head,-1,sizeof(head));
59     memset(dis,0x3f,sizeof(dis));
60     for(int i=1;i<=m;i++)
61     {
62         w1=0;
63         cin>>u1>>v1>>t1>>s1;
64         for(int j=1;j<=s1;j++)
65             cin>>n1,w1|=(1<<(n1-1));
66         add(u1,v1,t1,w1);
67         add(v1,u1,t1,w1);
68     }
69     dij(1);
70     int minn=1000000000;
71     for(int i=0;i<=(1<<13);i++)
72         minn=min(minn,dis[n][i]);
73     if(minn!=1000000000)
74         cout<<minn<<'\n';
75     else    cout<<-1<<'\n';
76     return 0;
77 }
复制代码

  怎么说,我的代码就是好看qwq。


四、写题心得:

  今天学了分层图,感觉挺简单的,实际上还是挺考思维的。这个题有点难度又是自己写出来的,所以真的还是很高兴,加油!

posted on   trh0630  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示