专栏文章
题解:P5189 [COCI 2009/2010 #5] ZUMA
P5189题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min20o3d
- 此快照首次捕获于
- 2025/12/01 19:16 3 个月前
- 此快照最后确认于
- 2025/12/01 19:16 3 个月前
十分有思维难度的一道区间动规题目。
一开始想到可以设计一个二维的状态,令 表示第 位到第 位的弹子被全部消除时需要放置的弹子的最少数量,然而很容易发现并不好转移,因为你并不好确定在 这个位置之前有多少个数字与 相同,也就不好确定你究竟要增加多少个弹子。所以考虑增加一个状态。
通过惊人的注意力,我决定加入一个状态,令 表示在第 到第 位的与 颜色不同的弹子已经全部消除时,将第 位到第 位的弹子以及之后 位与 颜色相同的弹子全部消除需要放置的弹子的最少数量。于是开始转移。
枚举区间长度与 ,再枚举 ,因为显然地,当 时,我不需要添加任何弹子,因此枚举毫无意义,所以只需枚举 中的所有数即可。进行初始化,此时 ,因为你要先消除第 位到第 位的所有弹子,所花费的代价也就是 ,然后再删除第 位以及之后 位与 颜色相同的弹子共计 位弹子,所花费的代价也就是 。当然,这样一般来说不会是最优的,因为在第 位到第 位的弹子中,可能存在颜色与 相同的弹子,因此枚举 中的所有 ,如果 ,那么可以令 ,后面这串柿子的意思就是先去掉第 位到第 位的弹子,然后再去掉第 位到第 位的弹子及之后的第 位以及我们所需要的之后的 位,共计 位。最后就会发现答案已经唾手可得,就是 。
代码如下。时间复杂度 。
CPP#include<bits/stdc++.h>
using namespace std;
const int N=105;
using ll=long long;
int dp[N][N][N],c[N],n,m;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>c[i];
for(int l=1;l<=n;l++){
for(int i=1;i<=n-l+1;i++){
int j=i+l-1;
for(int x=0;x<m;x++){
dp[i][j][x]=dp[i][j-1][0]+m-x-1;
for(int k=i;k<j;k++){
if(c[k]==c[j]) dp[i][j][x]=min(dp[i][j][x],dp[i][k][min(x+1,m-1)]+dp[k+1][j-1][0]);
}
}
}
}
cout<<dp[1][n][0];
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...