算法题——Ones and Zeroes(JAVA)动态规划

题目描述:
In the computer world, use restricted resource you have to generate maximum benefit is what we always want to pursue.

For now, suppose you are a dominator of m 0s and n 1s respectively. On the other hand, there is an array with strings consisting of only 0s and 1s.

Now your task is to find the maximum number of strings that you can form with given m 0s and n 1s. Each 0 and 1 can be used at most once.

Note:
The given numbers of 0s and 1s will both not exceed 100
The size of given string array won’t exceed 600.

读题:
有一定数量的0和1,组成数组中尽量多的字符串。类似于一个二维的背包问题。

知识储备:
背包问题
令V(i,j)表示在前i(1<=i<=n)个物品中能够装入容量为就j(1<=j<=C)的背包中的物品的最大价值,则可以得到如下的动态规划函数:

(1)   V(i,0)=V(0,j)=0 
(2) V(i,j)=V(i-1,j) ,j < wi
V(i,j)=max{V(i-1,j) ,V(i-1,j-wi)+vi) } ,j>wi

(1)式表明:如果第i个物品的重量大于背包的容量,则装人前i个物品得到的最大价值和装入前i-1个物品得到的最大价是相同的,即物品i不能装入背包;
第(2)个式子表明:如果第i个物品的重量小于背包的容量,则会有一下两种情况:
(a)如果把第i个物品装入背包,则背包物品的价值等于第i-1个物品装入容量位j-wi 的背包中的价值加上第i个物品的价值vi;
(b)如果第i个物品没有装入背包,则背包中物品价值就等于把前i-1个物品装入容量为j的背包中所取得的价值。显然,取二者中价值最大的作为把前i个物品装入容量为j的背包中的最优解。

解题思路:
动态规划:解决子问题并记录子问题的解
子问题为:要不要组建这个字符串。
在有i个待选字符串,原料为m n的情况下背包问题下:
最优解是什么?

第i+1个字符串可以选择放进背包或者不放进背包?
假设放进背包(前提是放得下),
那么f[m][n][i+1]=f[m-weight[i+1]][n-weight[i+1]][i]+1;
如果不放进背包,
那么f[m][n][i+1]=f[m][n][i]。
也就是:
f[m][n][i+1]=max(f[m][n][i],f[m-weight[i+1]][n-weight[i+1]][i]+1)。

提交代码:

public class Solution {
    private int[][][] dpTable;//保存状态结果
    public int findMaxForm(String[] strs, int m, int n) {
        int len = strs.length;
        int arr[][] = new int[len][2]; 
        int res = 0;
        //计算字符串中0和1的个数
        for (int i = 0; i < len; i++) {
            char[] chars = strs[i].toCharArray();
            int zero = 0;
            int one = 0;
            for (int j = 0; j < chars.length; j++) {
                if (chars[j] == '1')
                    one++;
                else
                    zero++;
            }
            arr[i][0] = zero;
            arr[i][1] = one;
            arr[i][2] = one+zero;
        }
        dpTable = new int[m+1][n+1][len];
        return FormTable(arr, len, m, n, 0);
    }
    private int FormTable(int[][] arr, int len, int m, int n, int pos) {
        if (m+n == 0 || pos == len) {
            return 0;
        }
        //如果之前已经算过了,则直接取出数据
        if (dpTable[m][n][pos] > 0) {
            return dpTable[m][n][pos];
        }
        int addCount = 0;
        //加入这条字符串的情况
        if (m >= arr[pos][0] && n >= arr[pos][1]) {
            addCount = FormTable(arr, len, m-arr[pos][0], n-arr[pos][1], pos+1) + 1;
        }
        //不加入这条字符串的情况
        int unaddCount = FormTable(arr, len, m, n, pos+1);
        if (addCount > unaddCount) {
            dpTable[m][n][pos] = addCount;
        } else {
            dpTable[m][n][pos] = unaddCount;
        }
        return dpTable[m][n][pos];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值