将字符串转换为其他字符串的最低成本

时间:2015-03-22 06:55:47

标签: string algorithm recursion dynamic-programming

给出2个相同长度N的字符串A和B.A包含' 0',' 1','?&#39 ;; B仅包含' 0' 0和' 1'。我们需要通过执行字符串A的允许操作序列来找到将A转换为B的最低成本。

允许以下操作:

  1. 更改' 0'到' 1'成本x
  2. 改变' 1'到' 0'成本y
  3. 改变'?'要么' 0'或者' 1'成本z
  4. 用成本t交换两个相邻的字符。
  5. 我们需要找到最低费用。

    示例:设N = 6,x = 1,y = 1000,z = 1,t = 1,A = 01 ?? 00,B = 001010则答案为4.

    如何使用动态编程解决这个问题?什么可以复发呢?请帮忙

2 个答案:

答案 0 :(得分:1)

让我们从一些观察开始:

  1. 如果我们匹配两个字符串中的所有字符串,则零会自动匹配。

  2. 操作顺序无关紧要。也就是说,我们可以假设我们首先进行所有更改(0到1,1对0,或者对某些东西),之后我们执行所有交换。

  3. 假设第一个字符串中的1个位置为(p_1, p_2, ..., p_n),第二个字符串中的位置为(q_1, q_2, ..., q_n)。然后,如果我们按排序顺序将pq匹配,我们会最小化掉期费用。

  4. 让我们看一下排名ii + 1。我们将balance[i]定义为长度为a的前缀中bi + 1中的数量的差异。然后,balance[i]交换将完全触及这两个元素。第3步暗示了这一主张。

  5. 所有这些观察都会导致以下动态编程解决方案:状态为(prefix length, current balance)。该值是处理给定长度前缀的最小成本,以便余额等于指定值。有O(N ^ 2)个州。如何进行过渡?我们可以尝试将所有内容放到a的当前位置并适当地计算成本。

  6. 答案是f(N, 0)

  7. 以下是一些代码:

    public class Task {
    
        final int INF = 1_000_000_000;
    
        int cost01;
        int cost10;
        int costUnknown;
        int costSwap;
    
        int getDeltaBalance(int c1, int c2) {
            return c1 - c2;
        }
    
        int getCost(char start, int want) {
            if (start == '?')
                return costUnknown;
            if (start - '0' == want)
                return 0;
            if (start == '1')
                return cost10;
            return cost01;
        }
    
        public void solve(Scanner in, PrintWriter out) throws IOException {
            int n = in.nextInt();
            cost01 = in.nextInt();
            cost10 = in.nextInt();
            costUnknown = in.nextInt();
            costSwap = in.nextInt();
            String a = in.next();
            String b = in.next();
            int[][] dp = new int[n + 1][2 * n + 1];
            for (int i = 0; i <= n; i++) {
                Arrays.fill(dp[i], INF);
            }
            dp[0][n] = 0;
            for (int pos = 0; pos < n; pos++) {
                for (int balance = -n; balance <= n; balance++) {
                    for (int curNumber = 0; curNumber <= 1; curNumber++) {
                        int newBalance = balance + getDeltaBalance(curNumber, b.charAt(pos) - '0');
                        if (newBalance < -n || newBalance > n)
                            continue;
                        int newCost = dp[pos][balance + n] + costSwap * Math.abs(balance)
                                + getCost(a.charAt(pos), curNumber);
                        dp[pos + 1][newBalance + n] = Math.min(dp[pos + 1][newBalance + n], newCost);
                    }
                }
            }
            out.println(dp[n][n]);
        }
    }
    

答案 1 :(得分:0)

大致上红宝石代码就是这样。它将通过ruby的几个在线挑战

def abc
u=gets.to_i
val = []
w=[]
for i in (1..u)
k=i+1
k3=i+2
costi = 0
costk = 0
costk3=0
n, x, y, z, t= [gets.split.map(&:to_i)].first
q = [x,y].min
if (1..1000).include?(x) and (1..1000).include?(y) and (1..q).include?(z)  and (1..1000).include?(t)
a=[gets.chomp.split(//)].first
a.keep_if{|v| v == "0"|| v == "1" || v == "?"}
a.keep_if{a.length == n}
c=a.clone
d=a.clone
b=[gets.chomp.split(//)].first
b.keep_if{|v| v == "0"|| v == "1"}
b.keep_if{b.length == a.length}
if b.length!=a.length
break
end 
val.push(n)
end
end_val = val.sort
count = (val.count*0.3).to_i
if (1..2000).include?(val.inject(0,:+)) &&    end_val.first(count).inject(0,:+)<=25
for p in (0..2)
if p == 0
m=a.length
for l in (0..m-1)
if a[l] != b[l]
   if a[l] == "0" 
     a[l] = "1"
     costi =  costi + x
  elsif a[l] == "1"
       a[l] = "0"
       costi = costi + y
  elsif a[l] == "?"
        a[l] = b[l]
        costi = costi + z
 end
end
end
elsif p ==1
m=a.length
$m =m
$i=0
while $i < $m do
if c[$i] != b[$i]
if c[$i] == b[$i+1] && c[$i+1] == b[$i]     
    c[$i] = b[$i]
    c[$i+1] = b[$i+1] 
    costk =costk + t
    $i +=1
elsif c[$i] == b[$i+1]
       e1 = c[$i+1] 

       c[$i+1] = c[$i]

       c[$i]=e1           
         costk =  costk + t
        if c[$i] == "?"
    c[$i] = b[$i]
    costk =  costk + z
    elsif c[$i] == "0"
  c[$i] = b[$i]
    costk =  costk + x
elsif c[$i] == "1"
c[$i] = b[$i]
    costk =  costk + y            
end
elsif c[$i+1] == b[$i]
     e2 = c[$i]  

 c[$i] = c[$i+i]

 c[$i+1]=e2
         costk =  costk + t
 if c[$i+1] == "?"
   c[$i+1] = b[$i+1]
    costk =  costk + z
 elsif c[$i+1] == "0"
  c[$i+1] = b[$i+1]
    costk =  costk + x
 elsif c[$i+1] == "1"
 c[$i+1] = b[$i+1]
    costk =  costk + y            
 end        
  elsif c[$i] == "?"
     c[$i] = b[$i]
    costk =  costk + z
 elsif c[$i] == "0"
  c[$i] = b[$i]
    costk =  costk + x
 elsif c[$i] == "1"
 c[$i] = b[$i]
    costk =  costk + y            
end
end
$i +=1
end
elsif p==2
m=a.length
$m =m
$i=$m-1
while $i >=0 do
if d[$i] != b[$i]
if d[$i] == b[$i-1] && d[$i-1] == b[$i]     
    d[$i] = b[$i]
    d[$i-1] = b[$i-1] 
    costk3 =costk3 + t
    $i -=1
    elsif d[$i-1] == b[$i]
        e4 = d[$i] 
        d[$i] = d[$i-i]
     d[$i-1]=e4
         costk3 =  costk3 + t  
       if d[$i-1] == "?"
    d[$i-1] = b[$i-1]
    costk3 =  costk3 + z
    elsif d[$i-1] == "0"
    d[$i-1] = b[$i-1]
    costk3 =  costk3 + x
    elsif d[$i-1] == "1"
    d[$i-1] = b[$i-1]
    costk3 =  costk3 + y            
    end 
    elsif d[$i] == "?"
    d[$i] = b[$i]
    costk3 =  costk3 + z
    elsif d[$i] == "0"
    d[$i] = b[$i]
    costk3 =  costk3 + x
    elsif d[$i] == "1"
    d[$i] = b[$i]
    costk3 =  costk3 + y            
    end
    end
    $i -=1
    end
    end
    end
    end
    v =[ costi, costk,costk3].min
    w.push(v)
    end
    puts w
    return w
    end
    abc