
一个更加便捷的方法:
先对输入的数字加一(increase函数),然后判断是不是不重复数(istarget函数)。如果不是,结束;否则,(modify函数)从左往右遍历数组,在重复的第二位加一(同时考虑进位问题),后面的所有数字按“0101”重复,因为要最小,所以最高位设为“0”。
这里我把“9”这个特殊的数字单独考虑,因为它的进位比较麻烦,这也是我的代码很长的原因。
#include <stdio.h> #include <string.h> #include <stdlib.h> #define FULL '9'+1 int istarget(char c[]) //判断是否为目标 { int i; for (i=0;i+1<strlen(c);i++) if (c[i]==c[i+1]) return 0; return 1; } int all9(char c[])//判断输入的数字是否全部为9 { int i; for (i=0;i<strlen(c);i++) if (c[i]!='9') return 0; return 1; } void increase(char c[]) { int i=strlen(c)+1; int j; if (all9(c))//全部为9的话会使数组长度加一,所以单独考虑 { for (j=1;j<i;j++) c[j]='0'; c[0]='1'; } else//否则就最后一位加一,从后往前遍历,如果该位为满(FULL),那么前一位加一 { i=strlen(c)-1; c[i]++; for (;i>0;i--) { if (c[i]==FULL) { c[i]='0'; c[i-1]++; } } } } void modify(char c[]) { if (c[0]=='9'&&c[1]=='9')//如果加一后是以“99”开头,那么也会使数组长度加一, //所以也单独考虑 { int i=strlen(c)+1; int j=0; c[j]='1'; for (j=1;j<i;j++) { if (j%2==1) c[j]='0'; else c[j]='1'; } } else { int i=0; char prev,latt; for (i=0;i+1<strlen(c);i++) { prev=c[i]; latt=c[i+1]; if (prev==latt)//一旦找到重复的两个数字就可以开始操作了 { if (prev=='9')//如果重复的数字是9,同样单独考虑 { c[i-1]++; if ((strlen(c)-i)%2==0)//按照从第一个重复数字到最后一位有 //多少数字的奇偶分类讨论 { for (;i<strlen(c);i+=2) { c[i]='0'; c[i+1]='1'; } } else { c[i++]='0'; for (;i<strlen(c);i+=2) { c[i]='1'; c[i+1]='0'; } } } else//否则就不存在进位问题 { c[++i]++; i++; if ((strlen(c)-i)%2==0) { for (;i<strlen(c);i+=2) { c[i]='0'; c[i+1]='1'; } } else { c[i++]='0'; for (;i<strlen(c);i+=2) { c[i]='1'; c[i+1]='0'; } } } break; } } } if (!istarget(c))//这里的递归是为了避免输入的数字为679898->679899->679901而错误 modify(c); } void solve(char c[]) { increase(c); if (!istarget(c)) modify(c); } int main() { int i,cas; char restore[1000]; scanf("%d",&cas); for (i=0;i<cas;i++) { memset(restore,0,1000); scanf("%s",restore); solve(restore); printf("case #%d:\n",i); printf("%s\n",restore); } return 0; }