目录
原题:
时间:1s 空间:256M
题目描述
输入格式
输出格式
样例输入
样例输出
题目大意:
主要思路:
dp转移:
dp初始化:
代码:
原题:
时间:1s 空间:256M
题目描述
大哈是个游戏王,尽管他的水平一言难尽,但他却总是这样自我称呼。小羽说如果你能把这个游戏通关了,你才算是个真的游戏王。这个游戏一开始你有n个连在一起的颜色块,第i个颜色块的颜色为。如果从i到j的颜色都一样,就说明i到j属于同一个连通块。比如[5,5,5]属于同一个连通块,[4,3,9,9]有3个连通块。游戏开始前大哈可以选择任意一个位置作为起始点,然后开始游戏。游戏的每一轮大哈可以将包含起始点的连通块的颜色变成任意一种其他的颜色。问大哈能将整个数组变成从1到n的连通块所需要的最少回合数。
大哈是个游戏王,尽管他的水平一言难尽,但他却总是这样自我称呼。小羽说如果你能把这个游戏通关了,你才算是个真的游戏王。这个游戏一开始你有n个连在一起的颜色块,第i个颜色块的颜色为。如果从i到j的颜色都一样,就说明i到j属于同一个连通块。比如[5,5,5]属于同一个连通块,[4,3,9,9]有3个连通块。游戏开始前大哈可以选择任意一个位置作为起始点,然后开始游戏。游戏的每一轮大哈可以将包含起始点的连通块的颜色变成任意一种其他的颜色。问大哈能将整个数组变成从1到n的连通块所需要的最少回合数。
输入格式
第一行一个整数n()
第二行n个整数()
输出格式
一个整数代表最少回合数
样例输入
4
5 2 2 1
样例输出
2
题目大意:
给你n个数,要你求把所有数变成相同一个数所需的最小操作数(每次操作可以将包含起点的连通块变为同一个数)
主要思路:
这题很难想到区间dp,我们用dp[l][r] 表示把l~r里的数变为同一个数的最小操作数,首先把每个连通块去重(就像把【2,2,3,3,2,2,4,4,4,4】变成【2,3,2,4】。
dp转移:
- v[l] == v[r] 那么就要dp[l][r] = dp[l+1][r-1]+1;注意:a[l+1]!=a[l],a[r-1]!=a[r]图:(画的有点草,谢谢谅解)
- 否则dp[l][r] = min(dp[l+1][r],dp[l][r-1])+1;图:(画的有点草,谢谢谅解)
剩下就没有什么好说的了
dp初始化:
dp[i][i] = 0把自己变成同一个数需要0步(i<=n)
代码:
#include<bits/stdc++.h>
using namespace std;
vector<int> v;
int dp[5010][5010];
int main()
{
int n;
cin>>n;
v.push_back(0);
int num=-1;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(i == 1)
{
num=x;
}
else
{
if(x == num)
{
}
else
{
v.push_back(x);
num = x;
}
}
}
memset(dp,0x3f,sizeof(dp));
for(int i=1;i<=v.size();i++)
{
dp[i][i] = 0;
}
for(int len=2;len<=v.size();len++)
{
for(int l=1;l+len-1<=v.size();l++)
{
int r=l+len-1;
if(v[l] == v[r]&&dp[l-1][r-1]!=v[l]&&dp[l-1][r-1]!=v[r])
{
dp[l][r] = dp[l+1][r-1]+1;
}
else
{
dp[l][r] = min(dp[l+1][r],dp[l][r-1])+1;
}
}
}
cout<<dp[1][v.size()];
return 0;
}