zoukankan      html  css  js  c++  java
  • 8.16题解

    T1

    废物除了搜索啥都不会打,连个垃圾DP都推不出来,事实上知道他是DP之后,依旧打了很久,我的DP状态和大家都不太一样,比较清奇,不过我觉得很好想,$dp[i][j][k]$表示第$i$位上为$k$前一位上为$j$的方案数,$j$和$k$均在$0 hicksim3$的范围内,$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
    ",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

    莫比乌斯反演,咕了

  • 相关阅读:
    【leetcode】1020. Partition Array Into Three Parts With Equal Sum
    【leetcode】572. Subtree of Another Tree
    【leetcode】123. Best Time to Buy and Sell Stock III
    【leetcode】309. Best Time to Buy and Sell Stock with Cooldown
    【leetcode】714. Best Time to Buy and Sell Stock with Transaction Fee
    【leetcode】467. Unique Substrings in Wraparound String
    【leetcode】823. Binary Trees With Factors
    【leetcode】143. Reorder List
    【leetcode】1014. Capacity To Ship Packages Within D Days
    【leetcode】1013. Pairs of Songs With Total Durations Divisible by 60
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11370388.html
Copyright © 2011-2022 走看看