hdu4662 简单搜索打表

题意:
     给你一个初始串"MI",这个串有三种操作,
(1)M后卖弄可以直接复制 ,MI -> MII
(2)三个III可以变成一个U,MUIII -> MUU
(3)连续的两个U可以直接删除,MIUUU -> MIU
每次输入一个字符串,问你这个字符串是不是MI变过来的.
 
思路:

     刚开始想都没想直接开个容器mark,然后搜索打表,控制的长度是1000000,直接敲完运行等了好几分钟都没打完,哎! sb了,后来仔细看了看题目发现 其实我们可以这样想,所有的U都是i经过一线变化过来的,因为刚开始的时候没有U,而i能变成u而u不能变成i,还有的就是这个串一定是开头是M,因为没有操作能让中间产生m,或者把M变没,这样就简单了,那么就相当于一开始有一个i,我们可以把i的个数*2(操作1) 或者把i的个数-6 (操作3),这样所有的可能i的个数都打出来,没多少1--300000个,对于输入的串我们先看下是不是只有开头有一个M,然后在统计下他有多少个i,一个u是三个i(还原操作2),然后根据当前的i的数量是否被mark输出Yes或者No,水题一枚.


#include<stdio.h>
#include<string.h>

#define N 1000100

char str[N];
int mark[N*3];

void DFS(int s)
{
   mark[s] = 1;
   if(s * 2 <= N * 3 && !mark[s * 2]) 
   DFS(s * 2);
   if(s - 6 >= 1 && !mark[s - 6])
   DFS(s - 6);
}

int main ()
{
   memset(mark ,0 ,sizeof(mark));
   DFS(1);
   int L ,ms ,t ,sum;
   scanf("%d" ,&t);
   while(t--)
   {
      scanf("%s" ,str);
      L = strlen(str);
      ms = sum = 0;
      for(int i = 0 ;i < L ;i ++)
      {
         if(str[i] == 'M') ms ++;
         if(i)
         {
            if(str[i] == 'I')
            sum ++;
            else sum += 3;
         }
      }
      if(ms != 1 || str[0] != 'M' || !mark[sum])
      puts("No");
      else puts("Yes");
   }
   return 0;
}
       
   
   
      

原文地址:https://www.cnblogs.com/csnd/p/12063136.html