zoukankan      html  css  js  c++  java
  • D. Flood Fill 区间DP 或lcs匹配

    题意 给定一串数字 相同的连续的数字可以同时 转换成一个相同数字 问最小几次可以全部转换成一个相同的数字

    法1:区间dp  dp[l][r][0/1]  0表示l r区间转化成和最左边相同需要多少次 1表示转化成和最右边相同 区间dp即可

     1 #include<bits/stdc++.h>
     2 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
     3 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
     4 #define F first 
     5 #define S second
     6 #define pii pair<int ,int >
     7 #define mkp make_pair
     8 #define pb push_back
     9 using namespace std;
    10 typedef long long ll;
    11 const int maxn=5e3+4;
    12 int c[maxn],a[maxn],b[maxn];
    13 int dp[maxn][maxn][2];
    14 int main(){
    15     int n;
    16     MS(dp,0x3f3f3f3f);
    17     scanf("%d",&n);
    18     FOR(i,1,n)scanf("%d",&c[i]);
    19     int cnt=0;
    20     int p=1;
    21     while(p<=n){
    22         if(c[p]!=c[p-1]||p==1)a[++cnt]=c[p];
    23         p++;
    24     }
    25     for(int i=1;i<=cnt;i++){
    26         dp[i][i][0]=dp[i][i][1]=0;
    27     }
    28     for(int len=1;len<=cnt;len++){
    29         for(int l=1,r=len+l;r<=cnt;r++,l++){
    30             dp[l][r][0]=min(dp[l][r][0],dp[l+1][r][0]+1);
    31 
    32             dp[l][r][0]=min(dp[l][r][0],dp[l+1][r][1]+!(a[r]==a[l]));
    33 
    34             dp[l][r][1]=min(dp[l][r][1],dp[l][r-1][1]+1);
    35 
    36             dp[l][r][1]=min(dp[l][r][1],dp[l][r-1][0]+!(a[l]==a[r]));
    37         }
    38     }
    39     cout<<min(dp[1][cnt][0],dp[1][cnt][1])<<endl;
    40     return 0;
    41 }
    View Code

    法2:LCS   从题目可以看出 如果转换成n个互相不连续的数字之后,如果所有数字都不相同则需要转换n-1次才能转换成一种答案

    如果存在 例如1 2 3 4 2 5   有区间[2,5] 这时如果先转化2 5 之间的数字 即可少转化一次 那么问题就转换成 求最大不相交的这种区间有多少个(相交不行,因为相交 中间夹的那个点就被更改了)

    而求最大相交的区间有多少个 就是把原序列翻转后的序列和原序列求lcs 因为lcs配对的过程  在原序列中的i  和翻转序列的j 就相当于 在原序列左右两边配对 所以不会相交 而因为是翻转的序列 所以会求两遍

    所以要/2 并且有一个区间的左右是重合的也就退化成了一个点,不能算 (这里在除以2的时候已经被消气了)减1 是因为 没有区间的时候是n-1的,每多一个区间都可以-1 这样答案就是总共的点数n-1-floor(lcs(s)/2);

     1 #include<bits/stdc++.h>
     2 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
     3 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
     4 #define F first 
     5 #define S second
     6 #define pii pair<int ,int >
     7 #define mkp make_pair
     8 #define pb push_back
     9 using namespace std;
    10 typedef long long ll;
    11 const int maxn=5e3+4;
    12 int c[maxn],a[maxn],b[maxn];
    13 int dp[maxn][maxn];
    14 int main(){
    15     int n;
    16     scanf("%d",&n);
    17     FOR(i,1,n)scanf("%d",&c[i]);
    18     int cnt=0;
    19     int p=1;
    20     while(p<=n){
    21         if(c[p]!=c[p-1]||p==1)a[++cnt]=c[p];
    22         p++;
    23     }
    24     memcpy(b,a,sizeof(a));
    25     reverse(b+1,b+cnt+1);
    26 //    for(int i=1;i<=cnt;i++)cout<<b[i]<<" ";
    27 //    puts("");
    28     for(int i=1;i<=cnt;i++){
    29         for(int j=1;j<=cnt;j++)
    30         {
    31             if(a[i]==b[j]){
    32                 dp[i][j]=dp[i-1][j-1]+1;
    33             }
    34             else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
    35         }
    36     }
    37     printf("%d
    ",cnt-1-dp[cnt][cnt]/2);
    38     return 0;
    39 }
    View Code

       

    两种方法参考:https://www.cnblogs.com/pkgunboat/p/10361375.html

    区间dp 参考:https://blog.csdn.net/moon_sky1999/article/details/87171499

  • 相关阅读:
    【解题报告】洛谷P1038 神经网络
    【解题报告】洛谷P6475 建设城市
    【解题报告】洛谷P4138 挂饰
    【解题报告】洛谷P3870 开关
    【解题报告】洛谷P1120 小木棍
    洛谷P1168 中位数
    FWT(快速沃尔什变换)
    lucas和扩展lucas
    exBSGS
    2_sat
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10585266.html
Copyright © 2011-2022 走看看