题目给定一些具有不同颜色和价值的玩具,求将其排列成颜色相同的放一起且按价值递增的形式,对原序列最少要操作几步。
一般让求将无序序列变为有序,都能转化成最长上升子序列问题,这个题目也不例外,主要是构造怎样的最长上升子序列。
题目的关键是颜色仅有四种,这样,通过枚举颜色序列,便可以得到任意一个玩具的位置,即知道了正确序列,然后按此序列对原序列求最长上升子序列即可。
题目的思路突破点是构造正确序列,以前做的题目都能很容易发现正确序列,思路被局限以致根本找不到正确序列,这个题目告诉我们,序列不一定是题目给的,只要能确定每个玩具的位置,就相当于获得了正确序列。
代码:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
struct node
{
int col,val;
int d;
}card[501];
int ord[5];
int ans;
int dp[501];
int c,n;
void lic()
{
for (int i=1;i<=c*n;i++)
card[i].d=n*(ord[card[i].col]-1)+card[i].val;
memset(dp,0,sizeof(dp));
int sum=0;
for (int i=1;i<=c*n;i++)
{
for (int t=0;t<i;t++)
{
if (card[i].d>card[t].d&&dp[i]<dp[t]+1)
dp[i]=dp[t]+1;
}
if (dp[i]>sum)
sum=dp[i];
}
if (ans>(c*n-sum))
ans=c*n-sum;
}
int main()
{
while (cin>>c>>n)
{
for (int i=1;i<=c*n;i++)
cin>>card[i].col>>card[i].val;
card[0].d=0;
ans=0x3f3f3f3f;
for (int i=1;i<=c;i++)
{
ord[i]=1;
if (c==1)
{
lic();
continue;
}
for (int t=1;t<=c;t++)
{
if (i!=t)
{
ord[t]=2;
if (c==2)
{
//cout<<" "<<ord[1]<<" "<<ord[2]<<endl;
lic();
continue;
}
for (int k=1;k<=c;k++)
{
if (k!=i&&k!=t)
{
ord[k]=3;
if (c==3)
{
//cout<<" "<<ord[1]<<" "<<ord[2]<<" "<<ord[3]<<" "<<ord[4]<<endl;
lic();
continue;
}
for (int j=1;j<=c;j++)
{
if (j!=i&&j!=t&&j!=k)
{
ord[j]=4;
//cout<<" "<<ord[1]<<" "<<ord[2]<<" "<<ord[3]<<" "<<ord[4]<<endl;
lic();
}
}
}
}
}
}
}
cout<<ans<<endl;
}
return 0;
}