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;
}
posted @ 2022-05-01 20:41  Jason142  阅读(27)  评论(0编辑  收藏  举报