逻辑:将重力应用于矢量

时间:2015-03-31 18:37:00

标签: algorithm math logic

有一种名为gravity(Vector[] vector)的方法。该向量包含数字序列。应用重力后,引力函数应返回一个新的向量,如下所述。

假设0是空气,1是砖。当施加重力时,砖块应该下降到最低水平。

设vector = [3,7,8]

将此转换为二进制,我们得到:
0 0 1 1 for 3
0 1 1 1 for 7
1 0 0 0 for 8

应用重力:
0 0 0 0即0 0 0 1 1是3
1 1 1 1,其为15

所以引力函数应该返回[0,3,15]。

希望你们能理解这个解释。我尝试了很多,但我无法弄清楚这个的逻辑。我观察到的一件事是在施加重力之前和之后矢量中的数字总和保持不变。

即,
对于上述情况,3 + 7 + 8 = 18 = 0 + 3 + 15.

4 个答案:

答案 0 :(得分:2)

我认为这就像计算总数' 1'一样简单。每个位置的位......

N 为输入向量大小, b 为输入元素的最长二进制长度

  1. 预先计算' 1'的总数。每个位置的位,存储在count [],O(N * b)
  2. 运行重力函数,即从count [],O(N * b)
  3. 重新生成N个数字

    总运行时间为O(N * b)

    以下是C ++中的示例代码

    
    
    #include<bits/stdc++.h>
    using namespace std;
    int v[5] = {3,9,7,8,5};
    int cnt[5] = {0};
    vector<int> ans;
    
    vector<int> gravity(){
    	vector<int> ret;
    	for(int i=0; i<5;i++){
    		int s = 0;
    		for(int j=0; j<5;j++)
    			if(cnt[j]){
    				s += (1<<j); cnt[j]--;
    			}
    		ret.push_back(s);
    	}
    	return ret;
    }
    
    int main(){
    	
    	// precompute sum of 1 of each bit
    	for(int i=0, j=0, tmp=v[i]; i<5; i++, j=0, tmp=v[i]){
    		while(tmp){
    			if(tmp&1) cnt[j]++;
    			tmp >>= 1; j++;
    		}
    	}
    	
    	ans = gravity();
    	
    	for(int i=ans.size()-1; i>=0; i--) printf("%d ", ans[i]);
    	
    	return 0;	
    }
    &#13;
    &#13;
    &#13;

    输出如下:

      

    成功时间:0记忆:3272信号:0

         

    0 1 1 15 15

答案 1 :(得分:1)

到目前为止,我能想到的唯一解决方案是使用嵌套的for循环:

  • vN整数
  • 的输入向量
  • D是每个整数中的位数
  • c跟踪砖块落下的最底部空间

该算法会检查数字i中的n位是否使用(n & (1<<i))进行设置,for (int j=0; j<D; ++j) int bit = 1<<j; int c = N-1; for (int i=N-1; i>=0; --i) if (v[i] & bit) { // if bit j of number v[i] is set... v[i] ^= bit; // set bit j in the number i to 0 using XOR v[c] ^= bit; // set bottom-most bit in the number i to 1 using XOR c -= 1; //increment by bottom row 1 } 适用于大多数类C语言。

C中的算法:

N

如果{{1}}很小并且知道它前进,你可以计算出每个数字值的真值表,并仅使用按位运算得到正确的结果而不是循环。

答案 2 :(得分:1)

从底部开始。除了底部已经有砖之外,那一排顶部的任何砖都会掉下来。所以,新的底线是:

bottom_new = bottom_old或top_old

新的顶部是:

top_new = bottom_old AND top_old

也就是说,如果两行中都有砖,那么新底行会有一块砖,但如果两行中都有砖,那么在新的顶行中只会出现一块砖

然后你就可以在堆栈中向前移动,新的顶行成为下一步的旧底行。

答案 3 :(得分:0)

解决方案:

所以我发现了一个需要递归的解决方案。虽然我不知道停止递归的条件。

向量v = [3,7,8]非常简单,无法解释为什么需要递归,所以考虑一个新的向量v = [3,9,7,8,5]

以二进制形式:

0 0 1 1 - a4  
1 0 0 1 - a3  
0 1 1 1 - a2  
1 0 0 0 - a1  
0 1 0 1 - a0 

迭代1:

0 0 0 0 - b7  (b7 = a4 AND b5)  
0 0 1 1 - b6  (b6 = a4 OR b5)  
0 0 0 0 - b5  (b5 = a3 AND b3) ignore this  
1 0 0 1 - b4  (b4 = a3 OR b3)
0 0 0 0 - b3  (b3 = a2 AND b1) ignore this  
0 1 1 1 - b2  (b2 = a2 OR b1)  
0 0 0 0 - b1  (b1 = a0 AND a1) ignore this    
1 1 0 1 - b0  (b0 = a0 OR a1)  

Intermediate vector = [b7, b6, b4, b2, b0] = [0, 3, 9, 7, 13]

迭代2:

0 0 0 0 - c7  (c7 = b4 AND c5)  
0 0 0 1 - c6  (c6 = b4 OR c5)  
0 0 0 1 - c5  (c5 = b3 AND c3) ignore this  
0 0 1 1 - c4  (c4 = b3 OR c3)  
0 0 0 1 - c3  (c3 = b2 AND c1) ignore this   
1 1 0 1 - c2  (c2 = b2 OR c1)  
0 1 0 1 - c1  (c1 = b0 AND b1) ignore this   
1 1 1 1 - c0  (c0 = b0 OR b1)  

Intermediate vector = [c7, c6, c4, c2, c0] = [0, 1, 3, 13, 15]  

迭代3:

0 0 0 0 - d7 (d7 = c4 AND d5)  
0 0 0 1 - d6 (d6 = c4 OR d5)  
0 0 0 1 - d5 (d5 = c3 AND d3) ignore this  
0 0 0 1 - d4 (d4 = c3 OR d3)  
0 0 0 1 - d3 (d3 = c2 AND d1) ignore this      
1 1 1 1 - d2 (d2 = c2 OR d1)  
1 1 0 1 - d1 (d1 = c0 AND c1) ignore this 
1 1 1 1 - d0 (d0 = c0 OR c1)  

Resultant vector = [d7, d6, d4, d2, d0] = [0, 1, 1, 15, 15]  

通过向后浏览向量,我得到了这个解决方案。

另一种解决方案:

  1. 构造一个多维数组,其中包含向量中所有元素的所有位(即),如果v = [3,7,8]则构造一个3x4数组并存储所有位。
  2. 计算每列中1的数量并存储计数。
  3. 从底部位开始,每个列的计数编号为1。
  4. 这种方法很简单,但需要构建大型矩阵。