原题网址: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:第一次写博客,可能我打字太啰嗦,写博客好累啊。