• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Free_rein
博客园    首页    新随笔    联系   管理    订阅  订阅

URAL-1830(Help in the RNOS)解题报告

首先先贴题目地址吧:http://acm.timus.ru/problem.aspx?space=1&num=1830。。。

     今天A这题很不爽,wa了n次,而且还超时。原来是自己写的递归把自己搞糊涂了,哎,路途遥远,被水题虐了。

  先讲题意:此题背景为帮助信息的查看,按F1打开帮助信息的第一页,每一页有两个按钮,一个是打开下一页,一个是关闭下一页。我们对这些页码从0~n-1进行编号,如果有很多页面是打开的,那么只能看到编号小的页面,1代表打开,0代表关闭;打个比如,有4个页面,1011,那么第0页,第2页和第3页是打开的,第1页是关闭的,所以我们只能看到第0页,看不到其它的,只有第0页能够通过F1来打开和关闭自己,其它的页面必须依赖上一页在操作,它给出两个字符串,第一个代表初始条件,页面的状态,第二便是你需要达到的状态,让你求操作的次数而且要求操作的次数最少。。。

对于它的样例:

3

111

000

正确操作是:111->011->010->110->100->000,所以总共5次,说到这里应该大家对题目都清晰了。

我们现在分析,对于字符串a和字符串b

如果a="101001"

  b="100101"那么我们就不必要考虑后两位,只用考虑前4个页,也就是说我们从字符串的尾巴开始模拟,如果相等则不操作,不相等则操作;

PS:假如a[i]和b[i]不相等,那么我们要修改a[i]位,则我们需要把a[i-1]位变成1,a[i-1]前面的所有位全部变成0,这样才能只显示第i-1位,而且操作第i位!

我们使用一个递归函数solve(int i,char k),表示我们把第i位变成字符k,而且从0~i-1位全部变成0;但是直接递归必定TLE,因为时间复杂度将是o(2^n);

所以我们需要优化,不难看出如果将00000变成00001,则需要操作(2^5)-1次,如果这一点理解了,那么我们可以直接进入我们的代码,如果不理解,那么

请你耐心一点归纳一下,相信你的能力可以很快得出这个简单结论,这里就不过多解释:

View Code
 1 //====================================================================
 2 //Name       :
 3 //Author     :hxf
 4 //copyright  :http://www.cnblogs.com/Free-rein/
 5 //Description:
 6 //Data       :2012.8.18
 7 //========================================================================
 8 #include<iostream>
 9 #include<algorithm>
10 #include<stdio.h>
11 #include<math.h>
12 #include<string>
13 #include<cstring>
14 #include<vector>
15 #include<stack>
16 #include<queue>
17 #include<map>
18 #define MAXN 100050
19 #define inf 10100
20 using namespace std;
21 int n;
22 char str[55];//初始状态
23 char set[55];//结束状态
24 long long ans;//记录总的操作次数
25 void solve(int a,char k)
26 {
27     if(a==0)//递归函数的终止条件,这里不解释
28     {
29         if(str[a]!=k)
30         {
31             ans++;
32             str[a]=k;
33         }
34         return;
35     }
36     if(str[a]==k)//如果str[a]等于k,那么将str[a-1]变为0,因为solve(a-1,'0')已经代表a-1前面的位都是0
37         solve(a-1,'0');
38     else//如果不等于
39     {
40         solve(a-1,'1');//讲str[a-1]变成1,才能修改str[a]
41         ans=ans+((long long)1<<a);//计数器加上2^a-1,然后加上修改str[a]的1次,正好2^a
42     }
43     for(int i=0;i<a;i++)
44         str[i]='0';//讲a前面的位全部置0
45     str[a]=k;
46 }
47 int main()
48 {
49     scanf("%d",&n);
50     scanf("%s %s",str,set);
51     int len=strlen(str);
52     ans=0;
53     for(int i=len-1;i>=1;i--)
54     {
55         if(str[i]==set[i])//如果相等就往前移
56             continue;
57         solve(i-1,'1');
58         ans++;
59         str[i]=set[i];
60     }
61     if(str[0]!=set[0])//对于i=0做单独判断
62         ans++;
63     printf("%lld\n",ans);
64     return 0;
65 }

 

 

 

posted @ 2012-08-18 21:56  Free_rein  阅读(470)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3