【RQNOJ 285】USACO2008 Feb 麻烦的聚餐(重庆一中高2018级信息学竞赛测验9) 解题报告
2016-09-10 17:03
399 查看
【问题描述】
为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批就餐的奶牛了。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。
第i头奶牛有一张标明她用餐批次 D_i 的卡片。虽然所有N头奶牛排成了很整齐的队伍,但谁都看得出来,卡片上的号码是完全杂乱无章的。
在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍,把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个他想要的每个组中的奶牛都站在一起的队列,例如111222333或者333222111。哦,你也发现了,FJ不反对一条前后颠倒的队列,那样他可以让所有奶牛向后转,然后按正常顺序进入餐厅。
你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。
【输入格式】
第1行: 1个整数:N
第2..N+1行: 第i+1行是1个整数,为第i头奶牛的用餐批次D_i
【输出格式】
第1行: 输出1个整数,为FJ最少要改几头奶牛卡片上的编号,才能让编号变成他设想中的样子
【输入样例】
5
1
3
2
1
1
【输出样例】
1
【数据范围】
1<=D_i<= 3
1<=N<=30,000
【来源】
队列中共有5头奶牛,第1头以及最后2头奶牛被设定为第一批用餐,第2头奶牛的预设是第三批用餐,第3头则为第二批用餐。如果FJ想把当前队列改成一个不下降序列,他至少要改2头奶牛的编号,一种可行的方案是:把队伍中2头编号不是1的奶牛的编号都改成1。不过,如果FJ选择把第1头奶牛的编号改成3,就能把奶牛们的队伍改造成一个合法的不上升序列了。
做题思路(错解):拿到这道题,在审题时以为队伍中的奶牛一定要分3批,于是推出了不完整的状态转移方程和边界,最后只得了40分。
解题思路(正解):根据题意,思路应该明确,主要算法就是动态规划,但为了方便分析状态转移方程,将之前顺序的队列与前后颠倒的队列分开考虑。
设状态函数f(i,j)表示前i头奶牛中,第i头奶牛卡片编号为j时的最少改动次数,接下来分析状态转移方程,第i头奶牛的编号可以为1、2、3,如果第i头奶牛原来的编号与现在的编号不符,则改动次数就要加1,当第i头奶牛的编号为1时,它前面的奶牛编号只能为1;当第i头奶牛的编号为2时,它前面的奶牛编号可以为1或者2;当第i头奶牛的编号为3时,因为编号为2的部分可以空缺,所以它前面的奶牛编号可以为1或者2或者3。所以,状态转移方程为if(a[i]!=j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)}+1
f(i,2)=min{f(i-1,1),f(i-1,2)}+1 f(i,1)=f(i-1,1)+1,if(a[i]==j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)} f(i,2)=min{f(i-1,1),f(i-1,2)} f(i,1)=f(i-1,1)。因为队伍中的奶牛不一定要分3批,所以边界条件为if(a[1]!=1) f(1,1)=1 else f(1,1)=0 ; if(a[1]!=2) f(1,2)=1 else f(1,2)=0
; if(a[1]!=3) f(1,3)=1 else f(1,3)=0。答案即在f(N,1),f(N,2),f(N,3)中取最小值。该算法的时间复杂度为O(3*n)。
因为队列可以前后颠倒,所以想要计算前后颠倒的序列满足条件时的最少改动次数,只需将输入的数据反向存储即可,动态规划与顺序的队列相同。
值得一提的是,该题的动态规划还有另外的做法,见麻烦的聚餐 解法2 from cqyz_yoyoku
考后反思:还是要注意审题,一定要仔细理解题目的意思,以防因对题目的曲解而造成的失误。
为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐。每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批就餐的奶牛了。由于奶牛们不理解FJ的安排,晚饭前的排队成了一个大麻烦。
第i头奶牛有一张标明她用餐批次 D_i 的卡片。虽然所有N头奶牛排成了很整齐的队伍,但谁都看得出来,卡片上的号码是完全杂乱无章的。
在若干次混乱的重新排队后,FJ找到了一种简单些的方法:奶牛们不动,他沿着队伍从头到尾走一遍,把那些他认为排错队的奶牛卡片上的编号改掉,最终得到一个他想要的每个组中的奶牛都站在一起的队列,例如111222333或者333222111。哦,你也发现了,FJ不反对一条前后颠倒的队列,那样他可以让所有奶牛向后转,然后按正常顺序进入餐厅。
你也晓得,FJ是个很懒的人。他想知道,如果他想达到目的,那么他最少得改多少头奶牛卡片上的编号。所有奶牛在FJ改卡片编号的时候,都不会挪位置。
【输入格式】
第1行: 1个整数:N
第2..N+1行: 第i+1行是1个整数,为第i头奶牛的用餐批次D_i
【输出格式】
第1行: 输出1个整数,为FJ最少要改几头奶牛卡片上的编号,才能让编号变成他设想中的样子
【输入样例】
5
1
3
2
1
1
【输出样例】
1
【数据范围】
1<=D_i<= 3
1<=N<=30,000
【来源】
队列中共有5头奶牛,第1头以及最后2头奶牛被设定为第一批用餐,第2头奶牛的预设是第三批用餐,第3头则为第二批用餐。如果FJ想把当前队列改成一个不下降序列,他至少要改2头奶牛的编号,一种可行的方案是:把队伍中2头编号不是1的奶牛的编号都改成1。不过,如果FJ选择把第1头奶牛的编号改成3,就能把奶牛们的队伍改造成一个合法的不上升序列了。
做题思路(错解):拿到这道题,在审题时以为队伍中的奶牛一定要分3批,于是推出了不完整的状态转移方程和边界,最后只得了40分。
解题思路(正解):根据题意,思路应该明确,主要算法就是动态规划,但为了方便分析状态转移方程,将之前顺序的队列与前后颠倒的队列分开考虑。
设状态函数f(i,j)表示前i头奶牛中,第i头奶牛卡片编号为j时的最少改动次数,接下来分析状态转移方程,第i头奶牛的编号可以为1、2、3,如果第i头奶牛原来的编号与现在的编号不符,则改动次数就要加1,当第i头奶牛的编号为1时,它前面的奶牛编号只能为1;当第i头奶牛的编号为2时,它前面的奶牛编号可以为1或者2;当第i头奶牛的编号为3时,因为编号为2的部分可以空缺,所以它前面的奶牛编号可以为1或者2或者3。所以,状态转移方程为if(a[i]!=j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)}+1
f(i,2)=min{f(i-1,1),f(i-1,2)}+1 f(i,1)=f(i-1,1)+1,if(a[i]==j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)} f(i,2)=min{f(i-1,1),f(i-1,2)} f(i,1)=f(i-1,1)。因为队伍中的奶牛不一定要分3批,所以边界条件为if(a[1]!=1) f(1,1)=1 else f(1,1)=0 ; if(a[1]!=2) f(1,2)=1 else f(1,2)=0
; if(a[1]!=3) f(1,3)=1 else f(1,3)=0。答案即在f(N,1),f(N,2),f(N,3)中取最小值。该算法的时间复杂度为O(3*n)。
因为队列可以前后颠倒,所以想要计算前后颠倒的序列满足条件时的最少改动次数,只需将输入的数据反向存储即可,动态规划与顺序的队列相同。
值得一提的是,该题的动态规划还有另外的做法,见麻烦的聚餐 解法2 from cqyz_yoyoku
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=30005; int N; int a[maxn],b[maxn]; /* f(i,j)表示前i头奶牛中,第i头奶牛卡片编号为j时的最少改动次数 if(a[i]!=j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)}+1 f(i,2)=min{f(i-1,1),f(i-1,2)}+1 f(i,1)=f(i-1,1)+1 if(a[i]==j) f(i,3)=min{f(i-1,1),f(i-1,2),f(i-1,3)} f(i,2)=min{f(i-1,1),f(i-1,2)} f(i,1)=f(i-1,1) 边界:if(a[1]!=1) f(1,1)=1 else f(1,1)=0 if(a[1]!=2) f(1,2)=1 else f(1,2)=0 if(a[1]!=3) f(1,3)=1 else f(1,3)=0 */ int d1[maxn][5],d2[maxn][5]; void solve() //动态规划 { memset(d1,100,sizeof(d1)); memset(d2,100,sizeof(d2)); if(a[1]!=1) d1[1][1]=1; else d1[1][1]=0; if(a[1]!=2) d1[1][2]=1; else d1[1][2]=0; if(a[1]!=3) d1[1][3]=1; else d1[1][3]=0; if(b[1]!=1) d2[1][1]=1; else d2[1][1]=0; if(b[1]!=2) d2[1][2]=1; else d2[1][2]=0; if(b[1]!=3) d2[1][3]=1; else d2[1][3]=0; for(int i=2;i<=N;i++) { for(int j=1;j<=3;j++) { if(a[i]!=j) { if(j==1) d1[i][1]=d1[i-1][1]+1; if(j==2) d1[i][2]=min(d1[i-1][1],d1[i-1][2])+1; if(j==3) d1[i][3]=min(d1[i-1][1],min(d1[i-1][2],d1[i-1][3]))+1; } else { if(j==1) d1[i][1]=d1[i-1][1]; if(j==2) d1[i][2]=min(d1[i-1][1],d1[i-1][2]); if(j==3) d1[i][3]=min(d1[i-1][1],min(d1[i-1][2],d1[i-1][3])); } } } for(int i=2;i<=N;i++) { for(int j=1;j<=3;j++) { if(b[i]!=j) { if(j==1) d2[i][1]=d2[i-1][1]+1; if(j==2) d2[i][2]=min(d2[i-1][1],d2[i-1][2])+1; if(j==3) d2[i][3]=min(d2[i-1][1],min(d2[i-1][2],d2[i-1][3]))+1; } else { if(j==1) d2[i][1]=d2[i-1][1]; if(j==2) d2[i][2]=min(d2[i-1][1],d2[i-1][2]); if(j==3) d2[i][3]=min(d2[i-1][1],min(d2[i-1][2],d2[i-1][3])); } } } int ans=1000000010; for(int i=1;i<=3;i++) ans=min(ans,min(d1 [i],d2 [i])); printf("%d\n",ans); } int main() { freopen("dinner.in","r",stdin); //freopen("dinner.out","w",stdout); scanf("%d",&N); for(int i=1;i<=N;i++) { scanf("%d",&a[i]); b[N-i+1]=a[i]; //反向存储输入数据,即将原队列前后颠倒 } solve(); return 0; }
考后反思:还是要注意审题,一定要仔细理解题目的意思,以防因对题目的曲解而造成的失误。
相关文章推荐
- NOIP2008普及组 排座椅(重庆一中高2018级信息学竞赛测验5) 解题报告
- BZOJ - 1609/USACO - Feb08 Silver Eating Together 麻烦的聚餐 重庆一中高2018级竞赛班第九次测试 2016.9.10 Problem 2
- USACO 月赛 劣质的草 (重庆一中高2018级信息学竞赛测验2) 解题报告
- USACO2.4.2 穿越栅栏(简单版本) (重庆一中高2018级信息学竞赛测验2) 解题报告
- 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
- BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
- bzoj1609 [Usaco2008 Feb]Eating Together麻烦的聚餐
- bzoj 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐(DP)
- vijos1037 搭建双塔(重庆一中高2018级信息学竞赛测验7) 解题报告
- [Usaco2008 Feb]Eating Together麻烦的聚餐(DP)
- [Usaco2008 Feb][BZOJ1609] Eating Together麻烦的聚餐
- bzoj1609【Usaco2008 Feb】Eating Together 麻烦的聚餐
- NOIP2011普及组 瑞士轮(重庆一中高2018级信息学竞赛测验4) 解题报告
- UVA1615 高速公路(highway)(重庆一中高2018级信息学竞赛测验5) 解题报告
- BZOJ 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
- 1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
- 分治算法练习题 病毒分裂(重庆一中高2018级信息学竞赛测验6) 解题报告
- 复赛模拟试题 物品选取(重庆一中高2018级信息学竞赛测验7) 解题报告
- [Usaco2008 Feb]Eating Together麻烦的聚餐[最长不下降子序列]
- [bzoj1609]: [Usaco2008 Feb]Eating Together麻烦的聚餐 递推