D. Flood Fill 区间DP 或lcs匹配
2024-10-19 05:19:02
题意 给定一串数字 相同的连续的数字可以同时 转换成一个相同数字 问最小几次可以全部转换成一个相同的数字
法1:区间dp dp[l][r][0/1] 0表示l r区间转化成和最左边相同需要多少次 1表示转化成和最右边相同 区间dp即可
#include<bits/stdc++.h>
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr))
#define F first
#define S second
#define pii pair<int ,int >
#define mkp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=5e3+;
int c[maxn],a[maxn],b[maxn];
int dp[maxn][maxn][];
int main(){
int n;
MS(dp,0x3f3f3f3f);
scanf("%d",&n);
FOR(i,,n)scanf("%d",&c[i]);
int cnt=;
int p=;
while(p<=n){
if(c[p]!=c[p-]||p==)a[++cnt]=c[p];
p++;
}
for(int i=;i<=cnt;i++){
dp[i][i][]=dp[i][i][]=;
}
for(int len=;len<=cnt;len++){
for(int l=,r=len+l;r<=cnt;r++,l++){
dp[l][r][]=min(dp[l][r][],dp[l+][r][]+); dp[l][r][]=min(dp[l][r][],dp[l+][r][]+!(a[r]==a[l])); dp[l][r][]=min(dp[l][r][],dp[l][r-][]+); dp[l][r][]=min(dp[l][r][],dp[l][r-][]+!(a[l]==a[r]));
}
}
cout<<min(dp[][cnt][],dp[][cnt][])<<endl;
return ;
}
法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);
#include<bits/stdc++.h>
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr))
#define F first
#define S second
#define pii pair<int ,int >
#define mkp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
const int maxn=5e3+;
int c[maxn],a[maxn],b[maxn];
int dp[maxn][maxn];
int main(){
int n;
scanf("%d",&n);
FOR(i,,n)scanf("%d",&c[i]);
int cnt=;
int p=;
while(p<=n){
if(c[p]!=c[p-]||p==)a[++cnt]=c[p];
p++;
}
memcpy(b,a,sizeof(a));
reverse(b+,b+cnt+);
// for(int i=1;i<=cnt;i++)cout<<b[i]<<" ";
// puts("");
for(int i=;i<=cnt;i++){
for(int j=;j<=cnt;j++)
{
if(a[i]==b[j]){
dp[i][j]=dp[i-][j-]+;
}
else dp[i][j]=max(dp[i-][j],dp[i][j-]);
}
}
printf("%d\n",cnt--dp[cnt][cnt]/);
return ;
}
两种方法参考:https://www.cnblogs.com/pkgunboat/p/10361375.html
区间dp 参考:https://blog.csdn.net/moon_sky1999/article/details/87171499
最新文章
- js获取URL地址栏中的参数
- html中表格的制作
- SQL简单语句总结习题
- 【CodeForces 577C】Vasya and Petya’s Game
- 谷歌联合 Adobe 发布 Noto 字体【免费下载】
- centos 安装完Nginx后,为什么访问不了?
- Maven-在eclipse创建maven项目
- 监控页面所有 ajax请求
- jquery的change 事件
- C#创建文件夹、文件
- (Problem 10)Summation of primes
- webform在页面生成的代码与事件回传
- Python Click 学习笔记(转)
- spring中jedis对redis的事务使用注意总结
- ABP入门系列(3)——领域层定义仓储并实现
- thymelead入门 git地址在文档最后
- host, nslookup, dig、whois
- C语言求行列式的值
- ssd物体检测模型训练和测试总结
- socket.io websocket