ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Noip模拟20 2021.7.19

2021-08-02 07:31:42  阅读:213  来源: 互联网

标签:head 20 2021.7 19 SNOW int 枚举 91 rp


T1 玩具

题目读错意思直接报零。。。

拼接方式没读懂以为是个数学题,用卡特兰数,可是的确想多了

数据范围表达出你怎么暴力都行,选择$n^3,dp$

相当于一片森林,每次多加一条边就合并成一棵树

在$dp$过程中统计合并的树的信息再算上贡献就行

T2 y

因为上次考试做过的v是一个将状态提取到数组里

这次为了暴力用了同样的方法

将状态枚举,提取出来后进行$XIN$队

 1 #include<bits/stdc++.h>//状压思想枚举每一种状态,然后爆搜
 2 #define int long long
 3 using namespace std;
 4 int n,m,d;bool flag;short pre[21];
 5 struct SNOW{int from,to,val,next;};SNOW e[1000000]; int head[1000000],rp;
 6 inline void add(int x,int y,int z){e[++rp]=(SNOW){x,y,z,head[x]};head[x]=rp;}
 7 inline void dfs(int x,int cnt){
 8     if(!cnt){flag=1;return;}
 9     for(int i=head[x];i;i=e[i].next) 
10         if(e[i].val==pre[cnt]) dfs(e[i].to,cnt-1);
11     return;
12 }
13 namespace WSN{
14     inline int main(){
15         scanf("%lld%lld%lld",&n,&m,&d); int tmp=0;
16         for(int i=1,u,v,c;i<=m;i++){
17             scanf("%lld%lld%lld",&u,&v,&c),add(u,v,c),add(v,u,c);
18             if(!c) tmp++;
19         }
20         if(tmp==m){
21             if(m==1) {cout<<0<<endl;return 0;}
22             else {cout<<1<<endl;return 0;}
23         }
24         int mzs=1<<d,ans=0;
25         for(int i=0;i<mzs;i++){
26             int st=i; flag=0;
27             for(int j=1;j<=d;j++) pre[j]=(st&1),st>>=1;
28             dfs(1,d); if(flag) ans++;
29         }
30         printf("%lld\n",ans);
31         return 0;
32     }
33 }
34 signed main(){return WSN::main();}
View Code

正解是一个叫$Meet In the Middle$的东西,其实可以很简单的理解为起点终点向中间去碰数。。

就分别统计以1到它长度为$len/2$的所有状态,距离1为$d$的点到中间$d/2$的所有状态

再依次拼接,查看有没有重复计算的总状态即可

复杂度最高的在于枚举状态,他分成$d/2$的两次枚举,比直接枚举$d$快了不知道多少。。

 1 #include<bits/stdc++.h>//状压思想枚举每一种状态,然后爆搜
 2 #define int long long
 3 using namespace std;
 4 int n,m,d,len;
 5 bool vis[1<<21];
 6 vector<int> vc1[91],vc2[91];
 7 bool f1[91][91][1025],f2[91][91][1025];
 8 struct SNOW{int from,to,val,next;};SNOW e[1000000]; int head[1000000],rp;
 9 inline void add(int x,int y,int z){e[++rp]=(SNOW){x,y,z,head[x]};head[x]=rp;}
10 namespace WSN{
11     inline int main(){
12         scanf("%lld%lld%lld",&n,&m,&d); int ans=0;
13         for(int i=1,u,v,c;i<=m;i++)scanf("%lld%lld%lld",&u,&v,&c),add(u,v,c),add(v,u,c);
14         len=d>>1; f1[0][1][0]=1;
15         for(int i=1;i<=len;i++) for(int j=1;j<=n;j++) for(int k=0;k<(1<<i);k++)
16             for(int u=head[j];u;u=e[u].next) f1[i][e[u].to][k<<1|e[u].val]|=f1[i-1][j][k];
17         int lenn;
18         if(d%2!=0) lenn=len+1;
19         else lenn=len;
20         for(int i=1;i<=n;i++) f2[0][i][0]=1;
21         for(int i=1;i<=lenn;i++) for(int j=1;j<=n;j++) for(int k=0;k<(1<<i);k++)
22             for(int u=head[j];u;u=e[u].next) f2[i][e[u].to][k<<1|e[u].val]|=f2[i-1][j][k];
23         for(int i=1;i<=n;i++){
24             for(int k=0;k<(1<<len);k++) if(f1[len][i][k]) vc1[i].push_back(k);
25             for(int k=0;k<(1<<lenn);k++) if(f2[lenn][i][k]) vc2[i].push_back(k);
26         }
27         for(int i=1;i<=n;i++) for(int j=0;j<vc1[i].size();j++) for(int k=0;k<vc2[i].size();k++)
28             if(!vis[(vc1[i][j]<<lenn|vc2[i][k])]) ans++,vis[(vc1[i][j]<<lenn|vc2[i][k])]++;
29         printf("%lld\n",ans);
30         return 0;
31     }
32 }
33 signed main(){return WSN::main();}
优秀的缩进

 

T3 z

超级麻烦的一道题,现在还没改出来,先沽了~~~

标签:head,20,2021.7,19,SNOW,int,枚举,91,rp
来源: https://www.cnblogs.com/hzoi-wsn/p/15088409.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有