• 区间dp


    https://zoj.pintia.cn/problem-sets/91827364500/problems/91827368971

    需要判断凸包,学了再来补;

    先说dp部分,

    dp[ i ][ j ]表示划分起点为i,终点为j的凸多边形所需的花费;

    dp [ i ] [ j ] =min ( dp[ i ][ j ] , dp[ i ] [ k ]+dp [ k ] [ j ] + cost [ i ] [ k ] +cost [ k ] [ j ] ) 

    http://poj.org/problem?id=2955

    括号匹配,经典区间dp;

    分两种情况;

    如果 ch[i] 与 ch【j】匹配,dp【i】【j】=max (dp[ i ]【j】,dp【i+1】【j-1】+2)

    如果不匹配;

    则按照区间dp模板;

    注意,枚举k得时候第一种情况也要计算一遍;

     1 #include<string.h>
     2 #include<iostream>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=110;
     6 char ch[maxn];
     7 int dp[300][300];
     8 int main()
     9 {
    10     while(scanf("%s",ch)!=EOF)
    11     {
    12         if(ch[0]=='e') break;
    13         int t=strlen(ch);
    14         for(int len=2;len<=t;len++)
    15         {
    16             for(int i=0;i+len-1<t;i++)
    17             {
    18                 int j=i+len-1;                    
    19                 if((ch[i]=='('&&ch[j]==')')||(ch[i]=='['&&ch[j]==']')) dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2);
    20                 for(int k=i;k<j;k++)
    21                 {
    22                     dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
    23                 }
    24             }
    25         }
    26         cout<<dp[0][t-1]<<endl;
    27         memset(dp,0,sizeof(dp));
    28         memset(ch,0,sizeof(ch));
    29     }
    30     return 0;
    31 }
    View Code

    http://poj.org/problem?id=1651

    区间dp;

    我的理解是:dp[ i ] [ k ] + dp[ k ] [ j ] +cost最后剩的元素只会左边和右边以及中间这个k,从i到k的最小值,加上从k-j的最小值,再加上去掉k所花的值;

     1 #include<string.h>
     2 #include<iostream>
     3 #include<cstdio>
     4 using namespace std;
     5 const int inf=0x3f;
     6 const int maxn=110;
     7 int ch[maxn];
     8 int dp[300][300];
     9 int main()
    10 {
    11     int n;
    12     cin>>n;
    13     memset(dp,inf,sizeof(dp));
    14     for(int i=1;i<=n;i++) cin>>ch[i],dp[i][i]=0,dp[i][i+1]=0;
    15     for(int len=3;len<=n;len++)
    16     {
    17         for(int i=1;i+len-1<=n;i++)
    18         {
    19             int j=len+i-1;
    20             for(int k=i;k<j;k++)
    21             {
    22                 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]+ch[i]*ch[k]*ch[j]);//对于当k被抽出时,左边界为i,右边界为j的方案数值。
    23             }
    24         }
    25     }
    26     cout<<dp[1][n]<<endl;
    27     return 0;
    28 }
    View Code

    https://codeforces.com/problemset/problem/149/D

    借鉴微博:https://blog.csdn.net/m0_38083668/article/details/82793071

    有空多做几遍,刚开始读错题了;输入的括号序列已知是合法的。

    括号序列合法,初始化时记录每个左括号所对应的右括号;

    对于区间i,j。如果i与j配对则dp[ i ] [ j ] [x ][ y] +=dp[ i + 1 ] [ j - 1 ] [  ] [  ];//类似于括号配对问题

    对于区间i ,j,端点i , j此次情况的方法数=dp[ i + 1 ] [ j - 1 ] [  ] [  ]的所有情况的和;加法原理;

    如果不配对:那么找到i对应合法括号位置tag,则dp[ i ] [ j ]...+=dp[ i ][ tag] [ ] [ ] *dp[ tag+1 ][ j ] [ ] [  ]; 

     1 #include<string.h>
     2 #include<iostream>
     3 #include<cstdio>
     4 using namespace std;
     5 #define int long long
     6 const int mo=1e9+7;
     7 char ch[800];
     8 int dp[710][710][3][3],p[800];//0代表不涂色,1代表涂红,2代表蓝
     9 void dfs(int l,int r)
    10 {
    11     if(l==(r-1))
    12     {
    13         dp[l][r][1][0]=1;
    14         dp[l][r][0][1]=1;
    15         dp[l][r][0][2]=1;
    16         dp[l][r][2][0]=1;
    17         return;
    18     }
    19     if(p[l]==r)
    20     {
    21         dfs(l+1,r-1);
    22         for(int i=0;i<=2;i++)
    23         for(int j=0;j<=2;j++){
    24         if(j!=1) dp[l][r][0][1]=(dp[l][r][0][1]+dp[l+1][r-1][i][j])%mo;
    25         if(i!=1) dp[l][r][1][0]=(dp[l][r][1][0]+dp[l+1][r-1][i][j])%mo;
    26         if(j!=2) dp[l][r][0][2]=(dp[l][r][0][2]+dp[l+1][r-1][i][j])%mo;
    27         if(i!=2) dp[l][r][2][0]=(dp[l][r][2][0]+dp[l+1][r-1][i][j])%mo;
    28         }
    29     }
    30     else{
    31         dfs(l,p[l]);
    32         dfs(p[l]+1,r);//不配对;
    33         for(int i=0;i<=2;i++)
    34         {
    35             for(int j=0;j<=2;j++)
    36             {
    37                 for(int k=0;k<=2;k++){
    38                     for(int h=0;h<=2;h++){
    39                     if(k==h&&h&&k) continue;
    40                     dp[l][r][i][j]=(dp[l][r][i][j]+dp[l][p[l]][i][k]*dp[p[l]+1][r][h][j]%mo)%mo;
    41                     }
    42                 }
    43             }
    44         }
    45     }
    46 }
    47 signed main()
    48 {
    49     scanf("%s",ch+1);
    50     int t=0;
    51     t=strlen(ch+1);
    52     for(int i=1;i<t;i++)
    53     {
    54        if(ch[i]==')') continue;
    55         int cnt=0;
    56         for(int j=i+1;j<=t;j++)
    57         {
    58             if(ch[j]=='(') cnt++;
    59             else cnt--;
    60             if(cnt==-1) {p[i]=j,p[j]=i;break;}
    61         }
    62     }
    63     dfs(1,t);
    64     int ans=0;
    65     for(int i=0;i<=2;i++)
    66     {
    67         for(int j=0;j<=2;j++)
    68         {
    69             ans=(ans+dp[1][t][i][j])%mo;
    70         }
    71     }
    72     cout<<ans<<endl;
    73 }
    View Code

    https://acm.sdut.edu.cn/onlinejudge3/problems/1309

  • 相关阅读:
    idea最新注册码
    pycharm中可以运行脚本(只在控制台运行,Debugger不运行,设置的断点没用)但是不能debug脚本
    VSCode 云同步扩展设置 Settings Sync 插件
    gist.github.com 无法访问解决办法,亲测永远有效!
    C# HttpWebRequest httpclient
    C# 图片处理
    powerdesigner逆向工程生成PDM时的列注释
    Ocelot网关治理
    Consul服务注册与发现
    CentOS 使用DVD1_DVD2作为本地离线的更新源
  • 原文地址:https://www.cnblogs.com/Showend/p/13264279.html
Copyright © 2020-2023  润新知