T1 景区路线规划(期望dp/记忆化搜索)

一看题目发现肯定是概率期望题,再仔细想想这三天做的题,就知道是个期望dp。

考试思路(错):

因为聪聪与可可的10分打法根深蒂固,导致在考试时想到了用深搜(就不知道当时为什么没想到用那个题的正解思路.....)

深搜其实打的也挺对的,应该是能拿到55分(因为没用记忆化和数组记录更新状态),可是还犯了一个致命错误: 出度没有找对!!

看题:每玩完一个项目后,小y和妹子会等概率的随机选择一个可以从当前项目直达的且来得及玩的项目作为下一个项目。

意思就是每次的出度会可能跟刚开始初始化记录的出度不统一,于是应每次都找出度:

for(int i=r[st];i;i=e[i].next){
int v=e[i].to;
if(time+e[i].value+s[v].c>k) continue;
out++;
}

每次的概率都是之前的概率连乘出来的。

这样就可以写出来了:

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int NN=10005;
4 int n,m,k,tmp;
5 double hh1,hh2,H1[105][485],H2[105][485];
6 struct node{
7 int c,h1,h2;
8 };node s[105];
9 struct SNOW{
10 int to,next,value;
11 };SNOW e[NN]; int tot,r[NN];
12 inline void add(int x,int y,int z){
13 e[++tot]=(SNOW){y,r[x],z};
14 r[x]=tot;
15 }
16 inline double dfs1(int st,int time){
17 int out=0;
18 if(time>k) return 0.0;
19 if(H1[st][time]) return H1[st][time];
20 for(int i=r[st];i;i=e[i].next){
21 int v=e[i].to;
22 if(time+e[i].value+s[v].c>k) continue;
23 out++;
24 }
25 H1[st][time]=s[st].h1;
26 if(!out) return H1[st][time];
27 for(int i=r[st];i;i=e[i].next){
28 int v=e[i].to;
29 H1[st][time]+=dfs1(v,time+e[i].value+s[v].c)/out;
30 }
31 return H1[st][time];
32 }
33 inline double dfs2(int st,int time){
34 int out=0;
35 if(time>k) return 0.0;
36 if(H2[st][time]) return H2[st][time];
37 for(int i=r[st];i;i=e[i].next){
38 int v=e[i].to;
39 if(time+e[i].value+s[v].c>k) continue;
40 out++;
41 }
42 H2[st][time]=s[st].h2;
43 if(!out) return H2[st][time];
44 for(int i=r[st];i;i=e[i].next){
45 int v=e[i].to;
46 H2[st][time]+=dfs2(v,time+e[i].value+s[v].c)/out;
47 }
48 return H2[st][time];
49 }
50 namespace WSN{
51 inline int main(){
52 scanf("%d%d%d",&n,&m,&k);
53 for(int i=1;i<=n;i++)
54 scanf("%d%d%d",&s[i].c,&s[i].h1,&s[i].h2);
55 for(int i=1,x,y,z;i<=m;i++){
56 scanf("%d%d%d",&x,&y,&z);
57 add(x,y,z); add(y,x,z);
58 }
59 for(int i=1;i<=n;i++){
60 hh1+=dfs1(i,s[i].c)/n;
61 hh2+=dfs2(i,s[i].c)/n;
62 }
63 printf("%.5lf %.5lf",hh1,hh2);
64 return 0;
65 }
66 }
67 signed main(){return WSN::main();}

小结:

概率期望专题里这种题型不少见,感觉比聪聪与可可简单一些,还是要记住正解代码呀!!!


T2 [中山市选2009] 树(树规/高斯消元)

看到题目第一个肯定想到高斯消元,数据也比较合适,刚好也特别像专题里的开关问题,于是。。。我们讲讲正解的树规(俏展了)

状态数组:dp[n][2][2]表示第n个点操作(摁或不摁)后的状态(开或关);

状态转移也分成四种情况来搞,就差不多了。

最终状态:min(dp[1][1][1],dp[1][0][1]);

其他の注意 :

1.建边的数组开二倍(要不然MLE40);

2.要提前将dfs的点的状态值保存,要不然以后转移状态会串数。。。

3.不能将两种暂时不合法状态赋太大的值,否则转移会爆long long

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int NN=105;
4 int n,g[105][2][2];//i->节点x 0/1->不按/按x 0/1->不开/开x
5 struct SNOW{
6 int to,next;
7 };SNOW e[NN<<1]; int tot,r[NN<<1];
8 inline void add(int x,int y){
9 e[++tot]=(SNOW){y,r[x]};
10 r[x]=tot;
11 }
12 inline void snow(int x,int fa){
13 g[x][0][0]=0; g[x][1][1]=1; g[x][1][0]=n+1; g[x][0][1]=n+1;
14 for(int i=r[x];i;i=e[i].next){
15 int v=e[i].to;
16 if(v==fa) continue;
17 snow(v,x);
18 int g00=g[x][0][0],g01=g[x][0][1],g10=g[x][1][0],g11=g[x][1][1];//提前记录,否则状态转移时值会改变
19 g[x][0][0]=min(g01+g[v][1][1],g00+g[v][0][1]);
20 g[x][0][1]=min(g00+g[v][1][1],g01+g[v][0][1]);
21 g[x][1][0]=min(g11+g[v][1][0],g10+g[v][0][0]);
22 g[x][1][1]=min(g10+g[v][1][0],g11+g[v][0][0]);
23 }
24 }
25 namespace WSN{
26 inline int main(){
27 while(1){
28 memset(g,0,sizeof(g));
29 memset(r,0,sizeof(r));
30 tot=0;
31 scanf("%d",&n);
32 if(n==0) break;
33 for(int i=1,x,y;i<n;i++){
34 scanf("%d%d",&x,&y);
35 add(x,y); add(y,x);
36 }
37 snow(1,0);
38 printf("%d\n",min(g[1][1][1],g[1][0][1]));
39 }
40 return 0;
41 }
42 }
43 signed main(){return WSN::main();}

附上特殊的高斯消元打法

 1 #include<bits/stdc++.h>
2 using namespace std;
3 const int NN=105;
4 int n,g[NN][NN],wsn;
5 inline void Guass(){
6 int cnt=1;
7 for(int i=1;i<=n;i++){
8 int r=cnt;
9 for(int j=cnt+1;j<=n;j++) if(g[j][i]>g[r][i]) r=j;
10 if(!g[r][i]) continue;
11 if(r!=cnt) for(int j=i;j<=n+1;j++) swap(g[r][j],g[cnt][j]);
12 for(int j=1;j<=n;j++)
13 if(j!=cnt&&g[j][i])//将所有的系数都变历一遍,保证只剩下自由元
14 for(int k=i;k<=n+1;k++) g[j][k]^=g[cnt][k];
15 cnt++;
16 }
17 }
18 inline void dfs(int x,int line){//暴力搜索自由元
19 if(line>=wsn) return;
20 if(!x){ wsn=line; return;}
21 if(g[x][x]) dfs(x-1,line+g[x][n+1]);
22 else{
23 if(g[x][n+1]) return;
24 dfs(x-1,line);
25 for(int i=x;i>=1;i--) g[i][n+1]^=g[i][x];
26 dfs(x-1,line+1);
27 for(int i=x;i>=1;i--) g[i][n+1]^=g[i][x];
28 }
29 }
30 namespace WSN{
31 inline int main(){
32 while(1){
33 wsn=0x7fffffff;
34 memset(g,0,sizeof(g));
35 scanf("%d",&n);
36 if(n==0) break;
37 for(int i=1,x,y;i<n;i++){
38 scanf("%d%d",&x,&y);
39 g[x][y]=g[y][x]=1;
40 }
41 for(int i=1;i<=n;i++) g[i][i]=g[i][n+1]=1;
42 Guass();
43 dfs(n,0);
44 printf("%d\n",wsn);
45 }
46 return 0;
47 }
48 }
49 signed main(){return WSN::main();}

T3 奇怪的道路(状压dp)

考试时候真的没看出来是状压,那个1000000007看着太像排列组合里的东西了(还是太弱。。。)

状压思路有点像动物园;

得出状态转移数组: dp[i][j][u][t]表示第i个结点用了j条边情况下的前u位连边数状态(奇数0,偶数1),i的前t个点是第四维开的意义:

思路:

1.循环的时候避免开头几位找的数大,用一个min(i,k)来卡住范围;

2.如果不连: dp[i][j][u][t-1]+=dp[i][j][u][t];

3.如果连: dp[i][j+1][u^1^(1<<t)][t]+=dp[i][j][u][t];

4.2,3步将会把所有状态转移至第四维是0上;

5.如果开头是偶数,可以进行下一个节点的转移:dp[i+1][j][u<<1][min(i,k)]+=dp[i][j][u][0];

6.最终状态: dp[n][m][0][0];

7.初始状态: dp[1][0][0][0]=1;

 

 1 #include<bits/stdc++.h>
2 #define int long long
3 using namespace std;
4 const int momomo=1000000007;
5 int n,m,k,dp[35][35][1<<10][10];
6 namespace WSN{
7 inline int main(){
8 scanf("%lld%lld%lld",&n,&m,&k);
9 dp[1][0][0][0]=1;
10 for(int i=1;i<=n;i++)
11 for(int j=0;j<=m;j++)
12 for(int u=0;u<(1<<k+1);u++){
13 for(int t=min(i,k);t>=1;t--){
14 dp[i][j][u][t-1]=(dp[i][j][u][t-1]+dp[i][j][u][t])%momomo;
15 dp[i][j+1][u^1^(1<<t)][t]=(dp[i][j+1][u^1^(1<<t)][t]+dp[i][j][u][t])%momomo;
16 }
17 if(!((u>>k)&1)) dp[i+1][j][u<<1][min(i,k)]=(dp[i+1][j][u<<1][min(i,k)]+dp[i][j][u][0])%momomo;
18 }
19 printf("%lld\n",dp[n][m][0][0]);
20 return 0;
21 }
22 }
23 signed main(){return WSN::main();}

马の思

由于种种原因吧,这次考的比较崩,这三道题改下来感觉自己拿100+还是可行的毕竟第一题确实比较水

搭嘎(但是),毕竟自己只是拿了9分,就没什么可吹嘘的理由了,只能是暂且埋头苦干吧

5.24已是历史,抬头往前看才有阳光。。。。暂且鼓励自己一波

马の想

SNack:

你们快集训了吧,暑假要加油鸭!

小小马:

肯定会的,并且一直想你。。

梦开始的地方(Noip模拟3) 2021.5.24的更多相关文章

  1. Noip模拟70 2021.10.6

    T1 暴雨 放在第一道的神仙题,不同的做法,吊人有的都在用线段树维护$set$预处理 我是直接$dp$的,可能代码的复杂度比那种的稍微小一点 设$f[i][j][p][0/1]$表示考虑了前$i$列, ...

  2. Noip模拟63 2021.9.27(考场惊现无限之环)

    T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...

  3. Noip模拟51 2021.9.12

    T1 茅山道术 考场上卡在了一个恶心的地方, 当时以为每次施法都会产生新的可以施法的区间,然后想都没细想, 认为不可做,甚至$dfs$也无法打,考后一问发现是自己想多了.. 新产生的区间对答案根本没有 ...

  4. Noip模拟84 2021.10.27

    以后估计都是用\(markdown\)来写了,可能风格会有变化 T1 宝藏 这两天老是会的题打不对,还是要细心... 考场上打的是维护\(set\)的做法,但是是最后才想出来的,没有维护对于是没有交. ...

  5. Noip模拟80 2021.10.18

    预计得分:5 实际得分:140?????????????? T1 邻面合并 我考场上没切掉的大水题....(证明我旁边的cty切掉了,并觉得很水) 然而贪心拿了六十,离谱,成功做到上一篇博客说的有勇气 ...

  6. Noip模拟79 2021.10.17(题目名字一样)

    T1 F 缩点缩成个$DAG$,然后根据每个点的度数计算期望值 1 #include<cstdio> 2 #include<cstring> 3 #include<vec ...

  7. Noip模拟76 2021.10.14

    T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...

  8. Noip模拟69 2021.10.5

    考场拼命$yy$高精度结果没学好$for$循环痛失$50pts$,当场枯死 以后一定打对拍,要不考后会... T1 石子游戏 首先要知道典型的$NIM$博弈,就是说如果所有堆石子个数的异或和为$0$则 ...

  9. Noip模拟61 2021.9.25

    T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...

  10. Noip模拟59 2021.9.22

    新机房首模拟变倒数 T1 柱状图 关于每一个点可以做出两条斜率分别为$1,-1$的直线, 然后题意转化为移动最少的步数使得所有点都在某一个点的两条直线上 二分出直线的高度,判断条件是尽量让这条直线上部 ...

随机推荐

  1. Vue状态管理Vuex简单使用

    状态管理保存在store\index.js中,简单说明如下 import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export def ...

  2. 企业快速开发平台Spring Cloud+Spring Boot+Mybatis+ElementUI 实现前后端分离

    鸿鹄云架构一系统管理平台 鸿鹄云架构[系统管理平台]使用J2EE技术来实施,是一个大型分布式的面向服务的JavaEE体系快速研发平台,基于模块化.服务化.原子化.热部署的设计思想,使用成熟领先的无商业 ...

  3. C# 获得当前方法 和 方法调用链 的 方法

    一个获得方法名的方法,depth表示调用此方法的回溯深度. 比如,A方法调用B方法,B方法调用GetCurrentMethodFullName(2),那么得到的结果是A方法的全名(namespace+ ...

  4. 模板引挚 jade ejs

    // asl sum翡翠 后台使用如下: const jade = require('jade') //pretty 美化的意思,指的是渲染的布局会美化   2020-2-15 var str = j ...

  5. ❤️❤️用最简单的方法在Webstorm中打开已存在项目 和 新建Vue项目 (亲测实用)❤️❤️

    ​ 目录 一:打开已存在项目时 二:新建一个vue项目 使用webstorm创建vue项目创建vue项目各个公司用的工具都不一样 最常见的有HBuilder X,WebStorm,Visual Stu ...

  6. 内部类访问外部类成员变量,使用外部类名.this.成员变量

    public class Outer { private int age = 12; class Inner { private int age = 13; public void print() { ...

  7. 为什么在匿名内部类中引用外部对象要加final修饰符

    当所在的方法的形参需要被内部类里面使用时,该形参必须为final. 为什么必须要为final呢? 首先我们知道在内部类编译成功后,它会产生一个class文件,该class文件与外部类并不是同一clas ...

  8. 使用metaweblog API实现通用博客发布 之 本地图片自动上传以及替换路径

    使用metaweblog API实现通用博客发布 之 本地图片自动上传以及替换路径 通过metaweblog API 发布博文的时候,由于markdown中的图片路径是本地路径,将导致发布的文章图片不 ...

  9. mysql数据库备份参数

    我用来实现自动全备份的脚本(可以满足一般有前后版本兼容要求的导出导入操作,我的字符集是latin1): mysqldump.exe -umyusername -pmypass -h localhost ...

  10. python对象引用和垃圾回收

    变量="标签" 变量a和变量b引用同一个列表: >>> a = [1, 2, 3] >>> b = a >>> a.appen ...