SRM476

      等考完继续更新,先把昨晚的SRM476写上先。昨晚只做出第一题,不过ranting却升了130+。500本来想dfs水一下,结果写错了,后来听说是状态压缩dp,不会。1000完全没看。感慨一下,只有教主和petr将三道全切了,抛离第三名300+分,这两大神教的对决果然没有第三个人能靠近得了啊。

 

 

DIV2

 

300 MatrixShiftings

 

    给出一个整数的矩阵和一个整数,问最少多少次滑动操作,可以让矩阵左上角的值和给定数相等,一次滑动操作,可以将所有行向上或向下循环移动,或将所有列向左或向右循环移动。

 

    因为矩阵中的数有可能通过最后一列再向右循环移动到达第一列,或最后一行向下循环移动到达第一行,所以有四种方式移到左上角。所以做法就是在矩阵中找到所有与给定数相同的数以后,选取到(0, 0),(0, col),(row, 0),(row, col)的最短的曼哈顿距离,即是答案。

 

 

500 Badgers

 

    有个人想养一些獾(这是啥?。。),现在有N个獾,要选一些来养。第i个獾每天需要吃hungry[i]个食物,并且这些獾看到其他獾吃东西,自己也会想吃更多的食物,如果养k个獾,那么第i个獾每天需要再多吃greedy[i]*(k-1)个食物。问题是,在最多每天提供totalFood的食物的情况下,问最多能养多少只獾。

 

    还是老规矩,枚举答案。从N开始往下枚举最多能养的数目k,求出每个獾每天需要的食物hungry[i]+greedy[i]*(k-1),再排序一下,求最少的k个的和。如果和小于等于totalFood,那么k就是结果。

 

 

1000 SubAnagrams

 

    简单的说SubAnagrams的意思,假如字符串A包含字符串B中的所有字符,且A中每种字符数目不少于B,那么称B是A的SubAnagrams。比如A为abaca,那么aaab、aaac、abca、aaa、abc这些都是A的SubAnagrams。现在问题是,给出一长串字符串X,问你可以最多拆成多少个子串S1, S2, ....Sn,让S1+S2+...+Sn等于X,且Si是S(i+1)的SubAnagrams。

 

    最开始直接用贪心写,果然错了。然后想dp,dp[i][j]表示最后一个字串是S[j...i]的最多拆分的个数,于是转移方程为:dp[i][j] = max(dp[j-1][k]+1),k是让S[k,...j-1]成为S[j....i]的SubAngrams的开始点。最开始写成O(n*n*n*26)的复杂度,结果有一组长500几乎全'A'的Case超时了。看大牛代码,知道了可以改进成O(n^3)。前两层循环枚举i, j,并统计[i..j]之间的字符出现个数Sum[26],第三层循环k从j-1往下枚举,遇到一个字符就将之前统计Sum[26]对应的减1后做dp,直到减到有Sum[i]为负,就退出k循环。关键代码:

 

 //dp[i][j]以i结尾,最后一段以j开头的最多的分割数
 memset(dp, 0, sizeof(dp));
 for(i = 1; i <= n; i++)
 {
  dp[i][1] = 1;
 }
 for(i = 2; i <= n; i++)
 {
  for(j = 2; j <= i; j++)
  {
   memset(sum, 0, sizeof(sum));
   for(k = j; k <= i; k++) sum[str[k]-'A']++;
   
   for(k = j-1; k >= 1; k--)
   {
    int t = str[k]-'A';
    sum[t]--;
    if(sum[t] >= 0)
    {
     if(dp[j-1][k]>0)
      dp[i][j] = max(dp[i][j], dp[j-1][k]+1);
    }
    else // 有字母超出数量限度,则退出
     break;
   }
   //dp[i][j] = max(dp[j-1][1..j-1]+1)
  }
 }

 

 

 

DIV1

 

250 Badgers

 

同DIV2 500。

 

 

550 FriendTour

 

还不会,留空。

你可能感兴趣的:(div)