充电混乱:Google Code Jam [2014]

时间:2014-04-26 09:22:32

标签: java algorithm

我发布此信息作为以下问题的解决方案,与其他人分享。 如果有更好的答案,那么请发帖。

Problem Statement

Shota农民有问题。他刚刚进入他新建的农舍,但事实证明他的所有设备都没有正确配置插座。作为一名现代农民,Shota拥有大量的智能手机和笔记本电脑,甚至拥有一台平板电脑供他最喜欢的牛和牛使用。他总共拥有N different devices

由于这些设备具有不同的规格并且由各种公司制造,它们每个都需要不同的电流来充电。类似地,房屋中的每个出口输出特定的电流。 An electric flow can be represented by a string of 0s and 1s of length L.

Shota希望能够同时为他的所有N个设备充电。巧合的是,他的新房子里正好有N个出口。为了配置来自插座的电流,有一个带L开关的主控制面板。第i个开关从房屋的每个出口翻转电流的第i位。例如,如果来自出口的电流是:

Outlet 0: 10
Outlet 1: 01
Outlet 2: 11

然后翻转第二个开关将重新配置电流:

Outlet 0: 11
Outlet 1: 00
Outlet 2: 10

如果Shota有智能手机需要流量“11”充电,需要流量“10”充电的平板电脑,以及需要流量“00”充电的笔记本电脑,然后翻转第二个开关会让他很开心!

Misa已经被Shota雇用来帮助他解决这个问题。她测量了房子出口处的电流,并发现它们都是不同的。决定Shota是否可以同时为他的所有设备充电,如果可能的话,找出需要翻转的最小开关数量,因为开关很大很重,Misaki不想要翻转超过她需要的东西。

4 个答案:

答案 0 :(得分:17)

这个问题的棘手部分是可以有多种翻转方式,但我们需要找到涉及最小翻转的方式。

这是我的算法来解决这个问题:

  1. 假设有N个设备需要D1...Dn位自行充电,电源插座可用输出:M1...Mn

  2. 获取设备所需的XOR功率,并且插座上的电源可让您了解要翻转的位数以匹配带电源插座的设备。

  3. 因此,一旦我们创建了设备和出口的XOR映射,每个二进制数中的1个数字表示所需的翻转次数。我们需要检查的是,是否可以将每个设备映射到XOR映射中具有相同二进制数的插座。

  4. 以下是一个例子:

    Number of Devices [N] : 3
    Number of bits in Electric charge [L] : 2
    Power need by Device 1 [D1] : 01
    Power need by Device 2 [D2]:11
    Power need by Device 3 [D3]:10
    
    Power available at Outlet 1 [T1] : 11
    Power available at Outlet 2 [T2] : 00
    Power available at Outlet 3 [T3] : 10
    
    XOR MAP
    
          Devices  D1  D2  D3
    Outlets
    T1             10  00  01
    T2             01  11  10
    T3             11  01  00
    

    现在在上面的地图中可以看出01只是所有设备为不同插座共享的二进制数。所以这里的答案是1翻转为01,只有一个1 [1表示需要翻转的数量]。如果共享了多个二进制数,那么我们将选择最少的二进制数。

    以下是此方法的java方法实现:

    private final int totalParams = 2, N = 0, L = 1;
    
    //Params contains value of N[devices] and L[charging bit]
    //cn contains power needed by each device
    //cs contains power available at outlet
    //return value is the number of bits to be flipped. -1 indicates not possible
    private int analyseChargeSetUp(int params[], BitSet[] cn, BitSet[] cs) {
    
            int retVal = -1;
    
            BitSet ms[] = new BitSet[params[this.N]];
    
            ArrayList<ArrayList<BitSet>> bxor = new ArrayList<ArrayList<BitSet>>();
    
            for (int i = 0; i < params[this.N]; i++) {
                BitSet temp = cn[i];
    
                // System.arraycopy(cs, 0, ms, 0, params[this.N]);
    
                for (int k = 0; k < params[this.N]; k++)
                    ms[k] = (BitSet) cs[k].clone();
    
                // System.out.println("Size: " + bxor.size());
                bxor.add(i, new ArrayList<BitSet>());
    
                for (int j = 0; j < params[this.N]; j++) {
                    ms[j].xor(temp);
                    bxor.get(i).add(j, ms[j]);
                }
            }
    
            // HashSet<BitSet> evalSet = new HashSet<BitSet>();
            HashMap<BitSet, BitSet> bitMap = new HashMap<BitSet, BitSet>();
    
            for (ArrayList<BitSet> bl : bxor) {
                for (int j = 0; j < params[this.N]; j++) {
                    BitSet temp1 = bl.get(j);
                    // if (!evalSet.add(temp1)) {
                    if (bitMap.get(temp1) == null) {
                        BitSet temp2 = new BitSet();
                        temp2.set(j);
                        bitMap.put(temp1, temp2);
                    } else {
                        bitMap.get(temp1).set(j);
                    }
                    // }
                }
            }
    
            BitSet resultGetter = new BitSet(params[this.L]);
            resultGetter.set(0, params[this.L] + 1, true);
            Iterator<BitSet> itr = bitMap.keySet().iterator();
            BitSet temp3 = new BitSet();
    
            while (itr.hasNext()) {
                temp3 = itr.next();
                if (bitMap.get(temp3).cardinality() == params[this.N]) {
                    if (temp3.cardinality() <= resultGetter.cardinality()) {
                        resultGetter = temp3;
                    }
                }
    
            }
    
            // if (resultGetter.cardinality() == params[this.L])
            // retVal = 0;
            // else if (resultGetter.cardinality() == 0)
            // retVal = -1;
            // else
            if (resultGetter.cardinality() > params[this.L])
                retVal = -1;
            else
                retVal = resultGetter.cardinality();
    
            return retVal;
    
        }
    

答案 1 :(得分:6)

不错的帖子和很棒的解决方案。我不知道Java中的BitSet类,谢谢!
对于实现,不严格需要存储所有XOR映射。事实上,可以逐步计算地图列之间的交叉点,以便找到所有可能的开关配置 此外,考虑到l的最大值是40(考虑到直到十分钟前我才知道BitSets :)),可以使用long来存储插座&#39;和设备&#39;配置。
因此,这是我的解决方案:

String solution(long[] o, long[] d) {

    HashSet<Long> xors = new HashSet<Long>();

    for (int j = 0; j < o.length; j++) {
        xors.add(o[0] ^ d[j]);
    }

    for (int i = 1; i < o.length; i++) {
        HashSet<Long> xors2 = new HashSet<Long>();
        for (int j = 0; j < o.length; j++) { 
            xors2.add(o[i] ^ d[j]);
        }
        for (Iterator<Long> it = xors.iterator(); it.hasNext();) {
            if (!xors2.contains(it.next())) {
                it.remove();
            }
        }
    }

    if (xors.isEmpty()) {
        return "NOT POSSIBLE";
    }

    Integer min = Integer.MAX_VALUE;
    for (long xor : xors) {
        min = Math.min(min, Long.bitCount(xor));
    }

    return min.toString();
}

答案 2 :(得分:0)

#include <iostream>
using namespace std;
#include<algorithm>
#include<stdio.h>
int main() {
long long int t,i,n,l,j,k,cur,m=0,count,max,q,w;
    char a[159][50],b[159][50];
    long long int d[159],e[159],f[159],flag,g;
cin>>t;
while(t--)
{
    cin>>n>>l;max=100;
    flag=0;
    m++;
    for(i=0;i<n;i++)``
    cin>>a[i];
    for(i=0;i<n;i++)
    cin>>b[i];
    for(i=0;i<n;i++)
    {
        d[i]=e[i]=0;long long int h=1;
        for(j=l-1;j>=0;j--)
        {
        if(a[i][j]=='0')
        q=0;
        else 
        q=1;
        if(b[i][j]=='0')
        w=0;
        else 
        w=1;

        d[i]+=q*h;
        e[i]+=w*h;
        h*=2;
        }
    }
    cur=0;
    sort(d,d+n);
    sort(e,e+n);
    for(i=0;i<n;i++)
    {
        flag=1;count=0;
        g=d[0]^e[i];

        for(k=0;k<n;k++)
        f[k]=d[k]^g;
        sort(f,f+n);
        for(k=0;k<n;k++)
        if(f[k]!=e[k])
        {
            flag=0;
            break;
        }

        for(k=0;k<l;k++)
        {
        if(g%2==1)
        count++;
        g=g/2;
        }
        if(flag==1)
        {
            if(max>count)
            max=count;
            cur=1;
        }

    }
    if(cur)
    printf("Case #%lld: %lld\n",m,max);
    else
    printf("Case #%lld: NOT POSSIBLE\n",m);
}
// your code goes here
return 0;
}

O(n ^ 2 log(n)+ n * l)解决方案。

答案 3 :(得分:0)

static int flipRecursion(List<String> i, List<String> d, int bit, int flip) {
        int f = 100000;
        // recusion ending here
        if (bit > d.get(0).length()) {
            if (isMatch(i, d)){
                return flip;
            } else {
                return f;
            }
        }
//      if (flip == f){
//          return flip;
//      }
        //noflip
        f = flipRecursion(i, d, bit+1, flip);
        //flip
        List<String> in = new ArrayList<>(i);
        in = flipBit(bit, in);
        return Math.min(flipRecursion(in, d, bit+1, flip+1), f);
    }