ACM-11月5日周日周末训练心得

来源:互联网 发布:怎样装修淘宝店铺首页 编辑:程序博客网 时间:2024/05/19 11:48

    昨天打了一场重现赛,一开始看的第11题,这道题大概的题意算是一共有n个兔子在一条数轴上的不同位置,最外面的兔子可以往里面的空隙跳,求最大的跳跃次数,一开始想的是用深搜去做,后来发现其实这个最大的跳跃次数就是相邻兔子的距离和 减去 第一段距离和最后一段距离中的较小值。 

for(int i=1;i<n;i++){     int x=a[i]-a[i-1]-1;     sum+=x;}int x=a[1]-a[0]<a[n-1]-a[n-2]?a[1]-a[0]:a[n-1]-a[n-2];cout<<sum-x+1<<endl;
     然后我看的第八题,这道题的背景还是比较熟悉的,就是三国杀中有主公、忠臣、反贼、内奸,各自获胜的条件跟桌游的一样,每个人的血量为h1、h2、h3、h4,行动顺序为主公反贼忠臣内奸,每次能攻击一个人使他减一滴血,问三个阵营每个阵营获胜的机率,前提:主公和忠臣不会互相攻击,我用的深搜做的,把每一种胜利的结局记录下来加到每个阵营的胜利次数中,最后每一个阵营获胜的机率就是自身胜利次数除以总的获胜次数。

   之后这周看的一道数位DP的题目,mountian number,这道题大致的意思就是要求出区间内偶数位大于奇数位的数字的个数,一个比较明白的数位DP,一个注意的是前导零,然后dp[i][j][k] 表示在第i个位置时,前面是j,现在这位是奇数位还是偶数位的数目。

int dfs(int pos,int pre,int odd,int zero,int doing)//pos表示当前位置,pre表示前一个数字,odd表示现在位置的奇偶性,zero标识是否还是前导0,doing表示是否枚举到了边界  {      if(pos==-1) return 1;      if(dp[pos][pre][odd]!=-1 && !doing)          return dp[pos][pre][odd];      int end = doing?bit[pos]:9;      int ans = 0;      for(int i = 0; i<=end; i++)      {          if(!(i||zero))              ans+=dfs(pos-1,9,0,zero||i,doing&&i==end);          else if(odd && pre<=i)              ans+=dfs(pos-1,i,!odd,zero||i,doing&&i==end);          else if(!odd && pre>=i)              ans+=dfs(pos-1,i,!odd,zero||i,doing&&i==end);      }      if(!doing)          dp[pos][pre][odd] = ans;      return ans;  }