4.10考试(过程)
上来看到problem1,想到了之前比赛做过的“游戏”问题,这两个题何其相似。
第一时间想考虑贪心,推了一会儿,发现这个题的不适用贪心策略(即使可能有这样的策略,判断也过于复杂)
不贪了,搜索
写到一半,想了想一些特殊判断剪枝,n与k均为正数,k小于n的情况下方法没得选,只能不断-1,于是把它加在前面了:
if(k<n) printf("%d\n",n-k),exit(0);
写搜索的时候也卡了一会,因为一开始想用一个变量ans记录,不现实啊!应该用数组记录到达某个点的步数。
problem2:单调序列,先找了找几个特点:
第一,不上升和不下降两个都要考虑;
第二,目标未知;
第三,要求最小改变量,而不是最小改变次数。
由第三点就知道肯定要动态规划来做,但是目标未知!
所以思考了一下,最优策略下改变结果一定都是原序列有的数
比如1 3 2 4 5 3 9 -->1 3 3 4 5 5 9,其中设b[]={1,2,3,4,5,9}作为目标数组。
然后就要考虑怎么dp了,这段最费时间,不过好在能够解决第一点(不上升和不下降,改变dp顺序即可)
然后开始写,中间还是要注意初始化。
int dp(){ memset(f,0x5f,sizeof(f)); memset(f[0],0,sizeof(f[0])); FOR(i,1,n){ FOR(j,0,m){ f[i][j] = min(f[i][j-1],f[i-1][j]+abs(a[i]-b[j])); } } int ans = f[n][m]; //正反搜两次 memset(f,0x5f,sizeof(f)); FOR(i,1,n){ ROF(j,m,0){ f[i][j] = min(f[i][j-1],f[i-1][j]+abs(a[i]-b[j])); } } ans = min(ans,f[n][m]); return ans; }
problem3,一眼看出来是树状数组/线段树问题。
(大样例的亿点问题好像对我没影响,能正常输出不知为什么)
两个操作是区间修改+区间查询?(这个超出我能力范围,但是勉强写了个单点查询+循环,可能超时)
先写了前面的树状数组一些基本函数(忘得差不多了)
然后才想起来要用b[i]=a[i]-a[i-1]来构成数组。
判断大于c的部分,卡了40分钟左右,后面就写暴力提交了。