Farmer John's cousin Ben happens to be a mad scientist. Normally, this creates a good bit of friction at family gatherings, but it can occasionally be helpful, especially when Farmer John finds himself facing unique and unusual problems with his cows.
Farmer John is currently facing a unique and unusual problem with his cows. He recently ordered NN cows (1≤N≤10001≤N≤1000) consisting of two different breeds: Holsteins and Guernseys. He specified the cows in his order in terms of a string of NN characters, each either H (for Holstein) or G (for Guernsey). Unfortunately, when the cows arrived at his farm and he lined them up, their breeds formed a different string from this original string.
Let us call these two strings AA and BB, where AA is the string of breed identifiers Farmer John originally wanted, and BB is the string he sees when his cows arrive. Rather than simply check if re-arranging the cows in BB is sufficient to obtain AA, Farmer John asks his cousin Ben to help him solve the problem with his scientific ingenuity.
After several months of work, Ben creates a remarkable machine, the multi-cow-breed-flipinator 3000, that is capable of taking any substring of cows and toggling their breeds: all Hs become Gs and all Gs become Hs in the substring. Farmer John wants to figure out the minimum number of times he needs to apply this machine to transform his current ordering BB into his original desired ordering AA. Sadly, Ben's mad scientist skills don't extend beyond creating ingenious devices, so you need to help Farmer John solve this computational conundrum.
The first line of input contains NN, and the next two lines contain the strings AA and BB. Each string has NN characters that are either H or G.
Print the minimum number of times the machine needs to be applied to transform BB into AA.
7 GHHHGHH HHGGGHH
2
First, FJ can transform the substring that corresponds to the first character alone, transforming BB into GHGGGHH. Next, he can transform the substring consisting of the third and fourth characters, giving AA. Of course, there are other combinations of two applications of the machine that also work.
Problem credits: Brian Dean
[/hide]
(Analysis by Jonathan Paulson, Benjamin Qi)
This is a greedy problem. There's not an obvious brute force to try; there are too many ways to flip different substrings in different orders. But if you just play around with a few examples, it's pretty easy to solve them by hand. To solve the problem, you need to guess a rule for how to solve them, convince yourself that it's right, and then code it. Greedy problems can be dangerous, because it can be easy to convince yourself something is right even if it actually doesn't work. The reward is that they're usually easier to code.
In this case, I first simplified the problem by observing that it doesn't matter what order you flip substrings in. All that matters is how many times each cow gets flipped. So let's assume we do the flips from left to right (sorted by the first cow they flip).
Now imagine scanning through the string from left to right. Whenever you find a mismatch, you have to fix it right now (because we just said we won't go backwards). So we definitely have to start a flip at this cow. Where should we end the flip? We should definitely keep going as long as there's mismatches, since it's free to fix these in the same flip. But once we get to a currently-matching cow, we should stop. Why? Because if we flip that cow, we'll immediately need to flip it again on the very next move. And any useful flip we wanted to do as part of this move, we could've just done as part of that move. So it never saves us any moves to keep going.
This gives us a pretty simple solution; just flip all the ranges of mismatching cows. We can count how many ranges there are with one pass through the strings - just count the number of positions that *start* a mismatch.
C++ code (from Jonathan Paulson):
#include <iostream> #include <string> using namespace std; using ll = long long; int main() { freopen("breedflip.in", "r", stdin); freopen("breedflip.out", "w", stdout); ll n; cin >> n; string A; string B; cin >> A >> B; ll ans = 0; bool mismatched = false; for(ll i=0; i<n; i++) { if(A[i] != B[i]) { if(!mismatched) { mismatched = true; ans++; } } else { mismatched = false; } } cout << ans << endl; }
Java code (from Nick Wu). The Java code follows a different rule than the one described above. It works just as well though. See if you can work out why.
import java.io.*; import java.util.*; public class Solution { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("breedflip.in")); PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("breedflip.out"))); int n = Integer.parseInt(br.readLine()); char[] a = br.readLine().toCharArray(); char[] b = br.readLine().toCharArray(); int ret = 0; while(!new String(a).equals(new String(b))) { ret++; int lhs = 0; while(a[lhs] == b[lhs]) lhs++; int rhs = n-1; while(a[rhs] == b[rhs]) rhs--; for(int i = lhs; i <= rhs; i++) { if(a[i] == 'G') a[i] = 'H'; else a[i] = 'G'; } } pw.println(ret); pw.close(); } }
Another way to view the problem:
Place additional H's before and after both strings. Now define
Adif[i]={1A[i]≠A[i+1]0otherwise
and define Bdif similarly. We want to convert Bdif to Adif, and each modification to B changes exactly two elements of Bdif. Thus, the answer is just the number of indices i such that Adif[i]≠Bdif[i] divided by two (as the numbers of ones in Adif and Bdif are always even, this is guaranteed to be an integer).
[/hide]
© 2025. All Rights Reserved. 沪ICP备2023009024号-1