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

  • 相关阅读:
    Android开发 使用 adb logcat 显示 Android 日志
    【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410
    C语言 结构体相关 函数 指针 数组
    C语言 命令行参数 函数指针 gdb调试
    C语言 指针数组 多维数组
    Ubuntu 基础操作 基础命令 热键 man手册使用 关机 重启等命令使用
    C语言 内存分配 地址 指针 数组 参数 实例解析
    CRT 环境变量注意事项
    hadoop 输出文件 key val 分隔符
    com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Too many connections
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10585266.html
Copyright © 2011-2022 走看看