151021的测试总结

12 篇文章 0 订阅
2 篇文章 0 订阅

第一题

【题目及题号】跳高 superoj944
【题解】
方法一(繁):用DP。
方法二(简):发现一个性质,在找能跳到的最大高度时,每次都跳到极限位置一定最优,且跳的台子数量最少。
要跳得最多的话直接找到最高的高度,小于等于它的数量就是答案。
开心写sort。
【考试ING】
我最后十分钟出了组全是0的数据然后发现了自己的错。Orz还好发现了Orz。看来下次交卷前二十分钟就该好好检查了。

第二题

【题目及题号】证明 superoj945
【题解】
[方法一]:
Dijikstra + Heap
(一)时间复杂度:
建图O(m+n)
离散化O(nlogn)
Dijikstra+Heap O(nlogn)
(二)分析过程:
将题目抽象出来,相当于给了我们一些带权的线段,要求我们用最小的权值,覆盖坐标轴1~n的范围。
应该很容易得到的一个性质,对于当前已覆盖距离的右坐标R,可用的转移只有左界在[L,R]范围内的线段。
这里写图片描述
如图片所示,对于3号点,只能使用2~4或者2~5向前进行移动。【我们这里强制使转移有序,实际上先使用哪条线段不影响结果】
如果对于每一个出现的点向上一个点建一条权值为0的边,把读入的边界从较小的点向较大的点建一条边(单向);就可以保证,每一次向前都需要付出代价,每一次取已覆盖区间的起点不需要代价。那么1为起点,n为终点跑最短路即可。如果无法到达n,那么输出-1。
现在遇到了另外一个问题,n的范围是10^9,如果对每一个坐标整点建边,复杂度是不可接受的。我们观察后发现,实际上每一个m只会带来两个可能被转移的点,那么将出现的点离散化,最坏的情况是有O(2*m)个点。Dijikstra+Heap可以轻易过掉这个题。
(三)注意事项
本题数据很强,卡掉了SPFA,请自觉写dijikstra+Heap。

[方法二]:
DP+优先队列+二分答案
f[i]表示用到第i个线段最少的花费。
f[i] = min(f[j])+c[i]; (li<=rj)
因为右界和花费都是单增的,所以可以在单调的队列中进行二分。

[方法三]:
Dp+线段树
fi表示证明了li~n相等且使用了第i个数学家所需要的最少花费。
fi = min(f[j])+c[i]; (lj<=ri且rj>ri)复杂度O(m^2)
现在考虑优化,将l,r离散化之后,让数学家按照l排序。
维护一个数组Gi,Gi = min(fj | lj=i);
然后求fi时使用(1,ri)直接的最小值来更新就好了。

【考试ING】
其实到现在我都不知道我当时怎么把这道题转成图论做的。标算是DP+线段树。Orz。
不过这倒是又明确了一点,觉得自己没有办法继续优化Dp的时候可以去想想别的算法。

第三题

【题目及题号】伪造 superoj946
【题解】
这个问题正着考虑是不太好想的,因为当前的最优值可能会影响到之后的值。
所以我们倒着来做,这样有一个好处,去掉了问题的后效性。
即如果当前值最大,当扫到前面的时候结果不会变差。
第一部分判断数字可以怎么转化使用floyd即可。
第二部分就需要分情况讨论。
每一个实际分数都受到了两个分数的限制,一个是满分,一个是前一次(倒着扫的前一次)的分数。
下面简称满分为full,前一次为last,本次为now;

情况一:len(full)>len(now) && len(last)>len(now) 直接使当前每一位最大即可。
情况二:len(full)小于len(now) || len(last)小于len(now) 发现无论如何都无法求解,所以输出no退出。
情况三:len(full)==len(now) || len(last)==len(now) 那么取两者直接的最小值来限制now即可。

限制有几种,例如3000,当前数的最高位如果选择了3,而后面无论如何都无法全部变成0,就应该让最高位减小成2继续判断。
所以要用dfs来实现。
【考试ING】
考虑掉了3000那种情况,然后开开心心输出NO了。Orz
然后有一个比较有用的东西,就是比较完大小后把last和full较小的存在full里面,可以简化代码。(不然就要写两个dfs)
调试的时候发现的问题有:
1.傻逼地把lena打成了lenb,导致compare函数写错。
2.dfs当中不小心修改了限制条件,本来now是要用来判断是否可转的,然后我修改了。【见代码】
WRONG

if(limit){
        for(int i=9;i>=0;i--)
            if(able[ori[x][pos]-'0'][i] && i<=mf[x][pos]-'0'){
                ori[x][pos] = i+'0';/*!!!!!!*/
                if(i == mf[x][pos]-'0') dfs(x,pos+1,len,1);
                else dfs(x,pos+1,len,0);
                if(found) return;
            }
    }

RIGHT

if(limit){
        for(int i=9;i>=0;i--)
            if(able[ori[x][pos]-'0'][i] && i<=mf[x][pos]-'0'){
                ans[x][pos] = i+'0';/*!!!!!!*/
                if(i == mf[x][pos]-'0') dfs(x,pos+1,len,1);
                else dfs(x,pos+1,len,0);
                if(found) return;
            }
    }

最后!!!!!千万不要再交错代码!!!!!!

题目预估分数实际分数
jump100100
proof100100
forge30~10030
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值