- 解法巧妙的一道题!
- 题意:n辆赛车,n条信息,第i条信息告诉你编号为i的车前面与后面分别有多少量车,求最少有多少条信息是错误的。
- 将问题转换一下,等价于最多有多少条信息是对的。
- 考虑每条信息意味着什么:知道了前后有多少量车,也就知道了这辆车的排名区间以及有多少量车与它并排!
- 每一条合法(对它自己而言)的信息可以确定一个排名区间,如a=1,b=2,n=5,它的排名区间就是[2,3],如果两条信息得出的排名区间有重叠,那么它们就是冲突的,反之不冲突。
- 我们可以做这样一个处理:每得出一个区间[i,j],就给cnt[i][j]的值+1,当cnt[i][j]的值加到j-i+1的时候不再加,因为这之后表示[i,j]的信息不能与前(j-i+1)条信息共同正确。
- 这个问题就转换成了一个区间最大不重复覆盖的问题!d[i]表示1~i的最大不重复覆盖值,d[i]=max(d[j]+cnt[j+1][i]) j∈[0,i-1]。
- 到此这一问题就已解决,考虑这个问题时可以把它拆分成两部分:转换成区间覆盖问题的合理性以及区间覆盖求法上的合理性。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int n,dp[1050],cnt[1050][1050],a,b,num;
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
if(a+b<=n-1&&cnt[a+1][n-b]<n-a-b)
cnt[a+1][n-b]++;
}
for(int i=1;i<=n;i++)
for(int j=0;j<i;j++)
dp[i]=max(dp[i],dp[j]+cnt[j+1][i]);
cout<<"Case "<<++num<<": "<<n-dp[n]<<endl;
memset(dp,0,sizeof(dp));
memset(cnt,0,sizeof(cnt));
}
return 0;
}