What is your average VP score rolling 2 versus 4 dice after an initial 3322xx roll?
Your overall expected value is what you might expect: 3.1121.
In other words, you should almost always get your 3-set of 3s, or a 4-set of 2s.
I threw together a simulator to help with this. Now, because I am a lamer, I used Java. It requires Java 7 because it uses &lt;&gt; notation. If you're using an older version, be warned. Here's the simulator, first off. Please feel free to pick it apart for functionality, but as far as style goes I know there's a million improvements to be made. This is a throw-away script if there ever one. There may be copy/paste typos and what not, but the code is actually fairly readable. I will add comments and edit as necessary, although I will group edits together to delay community-wikization.
import java.util.*;
import java.text.*;
class Tokyo {
    // shortcut for iterating over the faces of a die roll
    static final int[] face = {0,0,0,1,2,3};
    
    public static void main(String...args) {
        // the initial roll - there's no control over this
        final Roll init = new Roll(3,3,2,2,0,0);
        
        // strat1: reroll all non 3s
        // this gets all possible results and their counts from 
        // using strat 1 as our guide. see rollStrat1 on the Roll class
        Map&lt;Roll,Integer&gt; strat1roll1 = init.rollStrat1();
        report(strat1roll1);
        // now, for each of those rolls, we need to simulate using the same
        // strategy - the addTo makes sure we give proper credit to rolls that
        // come up more often
        Map&lt;Roll,Integer&gt; strat1roll2 = new HashMap&lt;&gt;();
        for(Roll roll : strat1roll1.keySet()) { // for each roll from roll 1
            Map&lt;Roll,Integer&gt; curr = roll.rollStrat1(); // reroll according to the strat
            addTo(strat1roll2, curr); // and store them all in the master map
        }
        // now count the results
        report(strat1roll2);
        
        // strat2: reroll all non doubles - comments ommited because it's the same as above
        Map&lt;Roll,Integer&gt; strat2roll1 = init.rollStrat2();
        report(strat2roll1);
        
        Map&lt;Roll,Integer&gt; strat2roll2 = new HashMap&lt;&gt;();
        for(Roll roll : strat2roll1.keySet()) {
            Map&lt;Roll,Integer&gt; curr = roll.rollStrat2();
            addTo(strat2roll2, curr);
        }
        
        report(strat2roll2);
        
        // strat3: mix the two
        Map&lt;Roll,Integer&gt; strat3roll2 = new HashMap&lt;&gt;();
        for(Roll roll : strat2roll1.keySet()) {
            Map&lt;Roll,Integer&gt; curr = roll.rollStrat3();
            addTo(strat3roll2, curr);
        }
        report(strat3roll2);
        
    }
    
    static DecimalFormat df = new DecimalFormat(&quot;###.00000&quot;);
    static void report(Map&lt;Roll,Integer&gt; map) {
        int sum = 0;
        int count = 0;
        for(Roll roll : map.keySet()) {
            sum += roll.score() * map.get(roll);
            count += map.get(roll);
        }
        double exval = ((double)sum) / (double)count;
        System.out.println(&quot;total: &quot; + sum);
        System.out.println(&quot;count: &quot; + count);
        System.out.println(&quot;exval: &quot; + df.format(exval)); 
    }
    
    
    
    // just merge the slave map into the master map
    static void addTo(Map&lt;Roll,Integer&gt; master, Map&lt;Roll,Integer&gt; slave) {
        for(Roll roll : slave.keySet()) {
            Integer count = master.get(roll);
            if(count == null) count = 0;
            master.put(roll, count + slave.get(roll));
        }
    }
    
    // reroll anything that isn't a 0 in the mask
    // if it is a non-0, that is the number that will show up in the roll
    // so if you want to re-roll a 2, in your strat method, turn that 2 into a
    // 0 so it gets re-rolled
    static Map&lt;Roll,Integer&gt; roll(Roll mask) {
        Map&lt;Roll, Integer&gt; rolls = new HashMap&lt;&gt;();
        // iterate over every possibly die roll
        for(int a = 0; a &lt; 6; a++) { 
        for(int b = 0; b &lt; 6; b++) { 
        for(int c = 0; c &lt; 6; c++) { 
        for(int d = 0; d &lt; 6; d++) {
        for(int e = 0; e &lt; 6; e++) { 
        for(int f = 0; f &lt; 6; f++) {
            
            int ra = mask.a == 0 ? face[a] : mask.a;
            int rb = mask.b == 0 ? face[b] : mask.b;
            int rc = mask.c == 0 ? face[c] : mask.c;
            int rd = mask.d == 0 ? face[d] : mask.d;
            int re = mask.e == 0 ? face[e] : mask.e;
            int rf = mask.f == 0 ? face[f] : mask.f;
            
            Roll roll = new Roll(ra, rb, rc, rd, re, rf);
            roll = roll.sort();
            if(rolls.containsKey(roll)) {
                rolls.put(roll, rolls.get(roll) + 1);
            } else {
                rolls.put(roll, 1);
            }
        }}}}}} // my code-review spidy sense is very pissed at me for this
        return rolls;
    }
    
    // unused, YAGNI I know... but this does illustrate all possible rolls
    static Map&lt;Roll,Integer&gt; possibleRolls() {
        return roll(new Roll(0,0,0,0,0,0));
    }
    
    // this represnts a roll, but it also represents a mask - lame, I know
    static class Roll {
        final int a,b,c,d,e,f; // the dice you have
        Roll(int a, int b, int c, int d, int e, int f) {
            this.a=a; this.b=b; this.c=c;
            this.d=d; this.e=e; this.f=f;
        }
        // welcome to Java - assumes they are properly sorted - a bad practice that
        // should be fixed if this grew beyond its current scope
        public boolean equals(Object o) {
            Roll ros = (Roll)o;
            Roll sor = this;
            return ros.a == sor.a &amp;&amp; ros.b == sor.b &amp;&amp; ros.c == sor.c 
                &amp;&amp; ros.d == sor.d &amp;&amp; ros.e == sor.e &amp;&amp; ros.f == sor.f;
        }
        // order doesn't matter for the result, but this is a perfect hash, that's cool
        public int hashCode() {
            return (a+1) * (b+1) * (c+1) * (d+1) * (e+1) * (f+1);
        }
        
        Roll sort() { // delegate sorting to Arrays =)
            int[] p = {a,b,c,d,e,f};
            Arrays.sort(p);
            return new Roll(p[0],p[1],p[2],p[3],p[4],p[5]);
        }
        
        int[] counts() { // convenience method
            int[] counts = new int[4];
            counts[a]++; counts[b]++; counts[c]++;
            counts[d]++; counts[e]++; counts[f]++;
            return counts;
        }
        
        int score() {
            int[] counts = counts();
            
            // trust the math =), or don't and work it out for yourself =)
            return (counts[1] &gt; 2 ? counts[1] - 2 : 0)
                 + (counts[2] &gt; 2 ? counts[2] - 1 : 0)
                 + (counts[3] &gt; 2 ? counts[3] : 0);
        }
        
        Map&lt;Roll,Integer&gt; rollStrat1() {
            return keepAll(3);
        }
        
        Map&lt;Roll,Integer&gt; keepAll(int k) {
        // reroll all non ks
            int ra = a == k ? k : 0; // the mask will have ks or 0s
            int rb = b == k ? k : 0;
            int rc = c == k ? k : 0;
            int rd = d == k ? k : 0;
            int re = e == k ? k : 0;
            int rf = f == k ? k : 0;
            return roll(new Roll(ra,rb,rc,rd,re,rf));
        }
        
        Map&lt;Roll,Integer&gt; rollStrat2() {
            // reroll anything that doesn't have 2x of something, except 0 - of course reroll 0s
            int[] counts = counts();
            int ra = counts[a] &gt; 1 &amp;&amp; a &gt; 0 ? a : 0;
            int rb = counts[b] &gt; 1 &amp;&amp; b &gt; 0 ? b : 0;
            int rc = counts[c] &gt; 1 &amp;&amp; c &gt; 0 ? c : 0;
            int rd = counts[d] &gt; 1 &amp;&amp; d &gt; 0 ? d : 0;
            int re = counts[e] &gt; 1 &amp;&amp; e &gt; 0 ? e : 0;
            int rf = counts[f] &gt; 1 &amp;&amp; f &gt; 0 ? f : 0;
            return roll(new Roll(ra,rb,rc,rd,re,rf));
        }
        
        Map&lt;Roll,Integer&gt; rollStrat3() {
            int[] counts = counts();
            if(counts[3] &gt; 2 &amp;&amp; counts[2] &gt; 2) {
                Map&lt;Roll,Integer&gt; map = new HashMap&lt;&gt;();
                map.put(this,score());
                return map;
            }
            if(counts[3] &gt; 2) {
                return keepAll(3);
            }
            if(counts[2] &gt; 2) {
                return keepAll(2);
            }
            return rollStrat1();
        }
    }

}

What the results are when it is run is (these values have changed - see edit history).
c:\files\j&gt;java Tokyo
total: 81756
count: 46656
exval: 1.75231
total: 5081940
count: 1632960
exval: 3.11210
total: 73872
count: 46656
exval: 1.58333
total: 1283040
count: 466560
exval: 2.75000
total: 1165885
count: 419909
exval: 2.77652

What does this tell us? Well, first it validates the system by coming up with values nearly identical to those calculated by other methods for the first roll. That's excellent news.
Now, let's look at the actual results. The number of different values explodes for strategy 1, mostly because it is rerolling 4 different dice on the first pass, and probably an average of 3.5 or so for the second pass. The count seems so much higher because of the uniqueness, but I adjusted for this 'problem' in the code.
The second strategy starts off less, and does stand for improvement. For example, if you don't get your 2s the second time, would it be better to dump all the 2s and go for 3s? This is where I implement strat 3.
Rather than start off with the results from strat 1, which are only focusing on the 3s, I instead use the first roll of strat 2 to focus on acquiring doubles. Then, I shift focus: if I have both sets, haha, we're done here... thanks... If I have a set of 3s or a set of 2s, I keep it and ditch the other set: after all, it's silly to try to aim for that 1/6 chance to pick up the other set - much better odds in ditching those dice and put them into something that's already bearing fruit. Lastly, if I don't have a set, I default to just rolling all non 3s, which is the same as the original 'strat 1' and is shown to have a higher single-roll result than strat 2. And that yields an excellent result but still not better.
Note the 5 reports:
strat 1 roll 1
strat 1 roll 2

strat 2 roll 1
strat 2 roll 2

strat 3 roll 2 (its roll 1 is strat 2's roll 1)

So the end result is that in this scenario, thus far the strategies indicate you should simply keep your 3s and go for it.