8.16题解

Posted hzjuruo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了8.16题解相关的知识,希望对你有一定的参考价值。

T1

废物除了搜索啥都不会打,连个垃圾DP都推不出来,事实上知道他是DP之后,依旧打了很久,我的DP状态和大家都不太一样,比较清奇,不过我觉得很好想,$dp[i][j][k]$表示第$i$位上为$k$迁移位上为$j$的方案数,$j$和$k$均在$0\thicksim3$的范围内,$0$ $1$ $2$参照题面,$3$代表此处有雷

思考

先来思考一下在大多数情况下那些方案对于相邻两位是合法的

00 两位上均没有雷且相邻位置上也没有雷
01 两位上均没有雷,后一个位置的相邻位置上有一个位置有雷,显然是右边
10 两位上均没有雷,前一个位置的相邻位置上有一个位置有雷,显然是左边
11 两位上均没有雷,且两个位置的相邻位置上都有一个位置有雷,显然左边一个右边一个
13 前一位上没雷,后一位上有雷
23 前一位左右两侧都有雷,后一位肯定是个雷
前一位是个雷,一共三种情况
31    32    33

初始化

由于$dp$定义的特殊性,我的初始化非常麻烦,直接初始化$dp[2]$,判断一下第一二位可能出现的情况,后面就直接从$dp[3]$开始转移即可

如果第一二位上均为$?$,那么我们只需要排除上面提到的9种情况中不合法的

10 上面有提到他需要前一位的左边有雷,但是第一位已经是最左,所以不合法
11 同上,第一位左侧不可能有雷
23 同上,左侧无雷

如果只有第一位是$?$,第二位已知直接就按照第二位,判断第一位可能情况即可

else if(a[1]==4)//4代表该处为?

    //当前为0,在上述的可能情况中选择,第一位只能为0
    if(a[2]==0)  dp[2][0][0]=1ll*1;
    //两种情况均可,对于前一种,第三位肯定是个3,当然,这是后话
    if(a[2]==1)  dp[2][0][1]=1ll*1;  dp[2][3][1]=1ll*1;
    //第二位为2,第一位肯定是个雷
    if(a[2]==2)  dp[2][3][2]=1ll*1;
    //第二位有个雷,第一位要么是个雷,要么不是雷那他的相邻位置上就必须标记有雷
    //注意23状态对于前两位,已经被判不合法
    if(a[2]==3)  dp[2][1][3]=1ll*1;  dp[2][3][3]=1ll*1;

同理判断只有第二位为$?$的情况,可以自己思考一下

else if(a[2]==4)

    if(a[1]==0)  dp[2][0][0]=1ll*1;  dp[2][0][1]=1ll*1;
    if(a[1]==1)  dp[2][1][3]=1ll*1;
    if(a[1]==3)  dp[2][3][1]=1ll*1;  dp[2][3][2]=1ll*1;  dp[2][3][3]=1ll*1;

两位都不为$?$要么不合法,要么就直接用,由于数据里没有不合法,所以我没判,严谨一点的话是需要判的

状态转移

当然又是一个长篇大论的分情况讨论,我们用$dp[i-1]$更新$dp[i]$

假设第$i$个位置上是0,由最初状态,状态只能是$00$或$10$,考虑这两种状态分别由哪些状态转移得来的,可以在列出的状态中选择合法状态,$00$可以由$00$和$10$转移得来,注意$dp[i]$的第二维和$dp[i-1]$的第三维之间的对应关系

第$i$个位置上为1,合法状态有$01$ $11$ $31$,$01$可以由$10$和$00$转移来,$11$由$31$转移来,$31$由$13$ $23$ $33$转移来

第$i$个位置为2或3时的状态转移可以自己想一想,想过之后去我的标程里对照一下,为5的时候就把前面的情况全和起来就可以了,我才不承认我是因为懒才没写全的

对于这种大量分情况讨论的题,转移的过程中一定要注意方案的合法性,保证补充不漏

统计答案

排除对最后一位来说的不合法状态即可

01 右侧不可能再出现雷
11 同上,右侧无雷
32 同上,右侧无雷
技术图片
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #define maxn 1001000
 5 #define ll long long
 6 #define mod 1000000007
 7 using namespace std;
 8 int n;
 9 ll ans;
10 int a[maxn];
11 char s[maxn];
12 ll dp[maxn][5][5];
13 int main()
14 
15     scanf("%s",s);  n=strlen(s);
16     for(int i=1;i<=n;++i)
17     
18         if(s[i-1]==0)  a[i]=0;
19         else if(s[i-1]==1)  a[i]=1;
20         else if(s[i-1]==2)  a[i]=2;
21         else if(s[i-1]==*)  a[i]=3;
22         else  a[i]=4;
23     
24     if(a[1]==4&&a[2]==4)
25     
26         dp[2][0][0]=1ll*1;  dp[2][0][1]=1ll*1;  dp[2][1][3]=1ll*1;
27         dp[2][3][1]=1ll*1;  dp[2][3][2]=1ll*1;  dp[2][3][3]=1ll*1;
28     
29     else if(a[1]==4)
30     
31         if(a[2]==0)  dp[2][0][0]=1ll*1;
32         if(a[2]==1)  dp[2][0][1]=1ll*1;  dp[2][3][1]=1ll*1;
33         if(a[2]==2)  dp[2][3][2]=1ll*1;
34         if(a[2]==3)  dp[2][1][3]=1ll*1;  dp[2][3][3]=1ll*1;
35     
36     else if(a[2]==4)
37     
38         if(a[1]==0)  dp[2][0][0]=1ll*1;  dp[2][0][1]=1ll*1;
39         if(a[1]==1)  dp[2][1][3]=1ll*1;
40         if(a[1]==3)  dp[2][3][1]=1ll*1;  dp[2][3][2]=1ll*1;  dp[2][3][3]=1ll*1;
41     
42     else  dp[2][a[1]][a[2]]=1ll*1;
43     for(int i=3;i<=n;++i)
44     
45         if(a[i]==0)
46         
47             dp[i][0][0]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;
48             dp[i][1][0]=dp[i-1][3][1];
49         
50         else if(a[i]==1)
51         
52             dp[i][0][1]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;
53             dp[i][1][1]=dp[i-1][3][1];
54             dp[i][3][1]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
55         
56         else if(a[i]==2)
57             dp[i][3][2]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
58         else if(a[i]==3)
59         
60             dp[i][1][3]=(dp[i-1][0][1]+dp[i-1][1][1])%mod;
61             dp[i][2][3]=dp[i-1][3][2];
62             dp[i][3][3]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
63         
64         else
65         
66             dp[i][0][0]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;
67             dp[i][1][0]=dp[i-1][3][1];
68             dp[i][0][1]=(dp[i-1][1][0]+dp[i-1][0][0])%mod;
69             dp[i][1][1]=dp[i-1][3][1];
70             dp[i][3][1]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
71             dp[i][3][2]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
72             dp[i][1][3]=(dp[i-1][0][1]+dp[i-1][1][1])%mod;
73             dp[i][2][3]=dp[i-1][3][2];
74             dp[i][3][3]=((dp[i-1][1][3]+dp[i-1][2][3])%mod+dp[i-1][3][3])%mod;
75         
76     
77     ans=((ans+dp[n][0][0])%mod+dp[n][1][0])%mod;
78     ans=((ans+dp[n][3][1])%mod+dp[n][1][3])%mod;
79     ans=((ans+dp[n][2][3])%mod+dp[n][3][3])%mod;
80     printf("%lld\n",ans);
81     return 0;
82 
超长分类讨论

T2

考试结束前三分钟,觉得可以和图论扯在一起,然而晚了

对于一个格子里水,他一定是沿着一条最矮的路流出去的,那么我们可以给相邻两点之间建边,以两点中的较大高度为边权,给最外面一圈点和外界连边,然后跑最小生成树,这样跑出来的就是最矮的一条路,也就是使所有点流出去的一条路,然后再$dfs$一遍,找到每个点流出去的路径上边权最大的边更新当前点的答案,因为一定是路径上最高的点限制了水流出去

技术图片
 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstdio>
 4 #define maxn 310
 5 #define bh(i,j) ((i-1)*m+j)
 6 using namespace std;
 7 struct node
 8     int from,to,w;
 9 a[maxn*maxn*4];
10 int n,m,tot,js;
11 int fa[maxn*maxn];
12 int head[maxn*maxn],to[maxn*maxn*8],xia[maxn*maxn*8],w[maxn*maxn*8];
13 int pd[maxn*maxn],ans[maxn*maxn];
14 int b[maxn][maxn];
15 int find(int x)
16 
17     if(fa[x]!=x)  return fa[x]=find(fa[x]);
18     return fa[x];
19 
20 void add(int x,int y,int z)
21 
22     to[++js]=y;  xia[js]=head[x];  w[js]=z;  head[x]=js;
23 
24 bool cmp(const node &a,const node &b)
25 
26     return a.w<b.w;
27 
28 void me(int x,int y)
29 
30     x=find(x);  y=find(y);
31     fa[y]=x;
32 
33 void dfs(int x)
34 
35     pd[x]=1;
36     for(int i=head[x];i;i=xia[i])
37     
38         int ls=to[i];
39         if(!pd[ls])  ans[ls]=max(ans[x],w[i]);  dfs(ls);
40     
41 
42 int main()
43 
44 //    freopen("2.in","r",stdin);
45 //    freopen("WA.out","w",stdout);
46     scanf("%d%d",&n,&m);
47     for(int i=1;i<=n;++i)
48     
49         for(int j=1;j<=m;++j)
50         
51             scanf("%d",&b[i][j]);
52             if(i==1||i==n||j==1||j==m)
53                 a[++tot].from=0;  a[tot].to=bh(i,j);  a[tot].w=max(0,b[i][j]);
54             if(i-1>=1)
55             
56                 a[++tot].from=bh(i-1,j);  a[tot].to=bh(i,j);
57                 a[tot].w=max(b[i][j],b[i-1][j]);
58             
59             if(j-1>=1)
60             
61                 a[++tot].from=bh(i,j-1);  a[tot].to=bh(i,j);
62                 a[tot].w=max(b[i][j],b[i][j-1]);
63             
64         
65     
66     for(int i=0;i<=n*m;++i)  fa[i]=i;
67     int tt=0;
68     sort(a+1,a+tot+1,cmp);
69     for(int i=1;i<=tot;++i)
70     
71         int fo=a[i].from,t=a[i].to;
72         if(find(fo)!=find(t))
73         
74             me(fo,t);  add(fo,t,a[i].w);  add(t,fo,a[i].w);
75             tt++;
76             if(tt==n*m)  break;
77         
78     
79     for(int i=0;i<=n*m+10;++i)  ans[i]=-1000000100;
80     dfs(0);
81     for(int i=1;i<=n;++i)
82     
83         for(int j=1;j<=m;++j)  printf("%d ",max(0,ans[bh(i,j)]-b[i][j]));
84         puts("");
85     
86     return 0;
87 
View Code

T3

莫比乌斯反演,咕了

以上是关于8.16题解的主要内容,如果未能解决你的问题,请参考以下文章

双周赛 52,单周赛 241 题解

精LintCode领扣算法问题答案:入门

题解目录

8.16安卓开发 注意事项

RabbitMQ3.8.16复制命令下载安装即可

《DSP using MATLAB》示例Example 8.16