UVA12283题解
题目:传送门
思路:
区间 dp,用 \(s_{i,j}\) 表示第 \(i\) 到第 \(j\) 次派对至少需要的衣服数,则结果为 \(s_{i,j}\) 若第 \(i\) 次和第 \(j\) 次需要的衣服种类相同,则可以使用相同的衣服,第 \(i+1\) 次到第 \(j-1\) 次派对所需要的衣服可以穿在第 \(i\) 次和第 \(j\) 次派对的衣服外面,用好后脱下,那么到第 \(j\) 次派对时,穿在最外面的就是第 \(i\) 次派对穿的那件衣服了,所以要穿的衣服数和第 \(i\) 次派对到第 \(j-1\) 次派对相等,状态转移方程为:
\[s_{i,j}=s_{i,j-1}
\]
若第 \(i\) 次和第 \(j\)次派对要穿的衣服不同,则要穿的衣服数和第 \(i\) 次到第 \(j-1\) 次要穿的衣服数 \(+1\) 相等,状态转移方程为:
\[s_{i,j}=s{i,j-1}+1
\]
用 for 循环来枚举中间点 \(k\),状态转移方程为:
\[s_{i,j}=min(s_{i,j},s_{i,k}+s_{k+1,j})
\]
需要注意输出格式里每行有两个空格。(详见代码)
代码:
#include <bits/stdc++.h>
using namespace std;
int t,n,m,a[105],s[105][105],i,j,k,l,o;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);//两行输入输出加速。
cin>>t;
for (l=1;l<=t;l++)
{
cin>>n>>m;
for (i=1;i<=n;i++)
{
cin>>a[i];
s[i][i]=1;//一次派对只用一件衣服。
}
for (o=2;o<=n;o++)//枚举 i 和 j 之间的距离。
{
for (i=1,j=i+o-1;j<=n;i++,j=i+o-1)
{
if (a[i]==a[j]) s[i][j]=s[i][j-1];//当第 i 次和第 j 次派对需要的衣服相同。
else s[i][j]=s[i][j-1]+1;//不同
for (k=i;k<j;k++)//枚举中间点。
{
s[i][j]=min(s[i][j],s[i][k]+s[k+1][j]);
}
}
}
cout<<"Case "<<l<<": "<<s[1][n]<<endl;//注意输出格式
}
return 0;
}