Kickdown UVA - 1588

 原题网址:https://vjudge.net/problem/UVA-1588;

说要把两个齿轮相互咬合在一起,两齿轮的锯齿和基底高度都为h,输入类似2112112112的数据来表示齿轮每一格的高度(2就代表凸起,1代表凹陷)。

输出两齿轮可以咬合情况下的最短 组合体的总体长度。

输入:

每次先输入一个master轮(底轮),然后再输入driven轮(上边的)。

每行一个非空字符串,并且长度不超过1000;(EOF结束)

输出:

每行一个整数表示最短组合体长度

 

实际上就是两个包含12的字符串,按位平行相加,每位不超过3;数据也不大,可以用暴力枚举做出所有情况,分类讨论要仔细一点,思路比较简单。

一共有四种情况,就用master:2112112112  driven:2212112 这组实例演示  ls=master.size;   ld=driven.size;

①:    2112112112        和     2112112112

  2212112                   2212112        

就是完全没对上,但是肯定符合要求,组合体长度为ls+ld,也就是最大的长度。

 

②:    2112112112            左边一部分没有完全进入master平行的区域(就把长的叫master了)。

     2212112     

这时要判断重合部分的组合长度是否超过3: 从情况①开始driven向下平移的位数称为i;重合位数j等于i;循环用master[0~i-1]和driven[ld-1-i]来相加比较3;

若可以通过检测则最小长度min=ls+ld-i;

③:   2112112112            driven完全进入master了;

         2212112

需要测试的长度j为ld,从master[i-ld]开始,drive[0]~drive[相加

④:  2112112112               可以说是镜像的②;

        2212112

重合长度j为ld-(i-ls)即ld+ls-i;master 从master[ls-1-j],driven[0]开始;

 

 1 #include<iostream>
 2 #include<string>
 3 //#include<vector>
 4 #define rep(i,n,t) for(int i=(n);i<(t);i++)
 5 #define per(i,n,t) for(int i=(n);i>(t);i--)
 6 
 7 #define MAX 250
 8 using namespace std;
 9 
10 //vector<int> C;
11 int main()
12 {
13     int min;
14     string S, D;
15     while (cin >> S >> D)
16     {
17         if (S.size() < D.size()) { string Temp = S; S = D; D = Temp; }
18         int ls = S.length(); int ld = D.length();
19         min = ls + ld;
20         rep(i, 1, ls + ld)//从1~ls+ld全部情况枚举出来
21         {
22             int flag = true;
23             if (i <= ld)//当driven没有从右边出头时;
24             {
25                 for (int j = 0; j < i; j++)//判断左边有没有露头
26                 {
27                     int high = S[j] + D[ld - i + j] - 96;
28                     if (high > 3)
29                     {
30                         flag = false;
31                         break;
32                     }
33 
34                 }
35                 if (flag&&min > (S.size() + ld - i))
36                 {
37                     min = S.size() + ld - i;
38                 }
39             }
40             else if (i <= ls)//一般情况
41             {
42                 for (int j = 0 ;j < ld; j++)
43                 {
44                     int high = S[i-ld+j] + D[j] - 96;
45                     if (high > 3)
46                     {
47                         flag = false;
48                         break;
49                     }
50 
51                 }
52                 if (flag&&min > ls)
53                 {
54                     min = ls;
55                     break;
56                 }
57             }
58             else//右边出头
59             {
60                 for (int j = 0 ; j < ld+ls-i; j++)
61                 {
62                     int high = S[i-ld+j] + D[j++]-96;
63                     if (high > 3)
64                     {
65                         flag = false;
66                         break;
67                     }
68 
69                 }
70                 if (flag&&min > i)
71                 {
72                     min = i;
73                 }
74             }
75         }
76         //C.push_back(min);
77         cout << min << endl;
78         S.clear(); D.clear();
79     }
80     /*rep(i, 0, C.size())
81     {
82         cout<<C[i]<<endl;
83     }*/
84     return 0;
85 }

 

总结:题很水,这个思路是马上就能想到的,也可能有更好的。

   这题代码改了好多遍,就是因为开始的时候拿起来就写,想把几种情况写到一起,后来发现被三种情况的组合判断加上不同的i,j,ls,ld序号头都晕了

   写到一起确实可以很精简,但是做题太没效率,可读性也差。

   下次不管做什么题,原版一定要先把每步写清楚,代码的书写好是目标,题目高效ac才是目的。

   ps:做算法题感觉一定要带上笔和纸,空想太难受了。pps:第一次写博客,可能我打字太啰嗦,写博客好累啊。

 

posted @ 2019-03-06 17:53  超融合  阅读(250)  评论(0编辑  收藏  举报