链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3990
题意:
输入两个等长(长度不超过100)的串S和T,其中S包含字符0, 1, ?,但T只包含0和1。
你的任务是用尽量少的步数把S变成T。每步有3种操作:把S中的0变成1;把S中的“?”变成0或者1;
交换S中任意两个字符。如果S不能变为T则输出-1。
分析:
既然S中的0可以变为1,'?'可以变为0或1,那么S不能变为T的唯一情况是S中1的个数比T多。
可以把解题过程分为几个阶段:
阶段一:分别统计S和T中1的个数,判断是否有解。
阶段二:如果S中某个位置是'?'且T中对应的位置是1,S中1的个数又比T少,则先把该位置变为1,以减少交换次数。
阶段三:将S中剩余的'?'变为0或1,只要能让S和T中1的个数相等,可以随意变换。
阶段四:判断是否需要把S中的某些0变为1,以及需要交换的次数。
代码:
1 #include <cstdio> 2 #include <cstring> 3 4 const int UP = 100 + 5; 5 char s[UP], t[UP]; 6 7 int judge(){ 8 int sum = 0; //1的个数 9 for(int i = 0; s[i]; i++) sum += (t[i]=='1'), sum -= (s[i]=='1'); 10 if(sum < 0) return -1; //阶段一:判断是否有解 11 12 int change = 0, remain = strlen(s); //变换的次数,对应位置不相等的总个数 13 for(int i = 0; s[i]; i++) if(s[i] == '?' && sum && t[i] == '1'){ 14 s[i] = '1'; 15 change++; 16 sum--; 17 } //阶段二:优先把S中的某些位置变成1 18 19 for(int i = 0; s[i]; i++){ //阶段三:将S中剩余的'?'变为0或1 20 if(s[i] == '?'){ 21 change++; 22 if(sum) s[i] = '1', sum--; 23 else s[i] = '0'; 24 if(s[i] == t[i]) remain--; 25 } 26 else if(s[i] == t[i]) remain--; 27 } 28 change += sum; //阶段四:把S中的某些0变为1,以及累加交换的次数 29 remain -= sum; 30 return change + remain / 2; 31 } 32 33 int main(){ 34 int T; 35 scanf("%d", &T); 36 for(int cases = 1; cases <= T; cases++){ 37 scanf("%s%s", s, t); 38 printf("Case %d: %d ", cases, judge()); 39 } 40 return 0; 41 }