题解/算法 {3130. 找出所有稳定的二进制数组 II}

题解/算法 {3130. 找出所有稳定的二进制数组 II}

@LINK: https://leetcode.cn/problems/find-all-possible-stable-binary-arrays-ii/;

很容易想到一个DP: (i,j,k,l) 表示[0...i]的序列 其中有j1, 且最后有连续kl(0/1) 的合法序列(即不存在连续相同子段长度>L)
. DP转换的话, 如果k>1 那么等于(..., k-1, l); 否则当k==1时 他等于(...,1|2|3|...|L, l^1)之和;
可他的时间是N^3的;

考虑把k优化掉; 令(i,j,l) 表示[0...i]的序列 其中有j个1 且末尾为l的 合法序列(即不存在连续相同子段长度>L)
. 你可能认为, 我们肯定是需要记录末尾连续子段长度的呀, 否则怎么跟L联系到一起呢? 别着急, 先这么定义 一步步来;
比如对于形如[..., p, 1]的序列, 他可以继承[..., p=0]这肯定没问题; 关键是 如果要继承[..., p=1](设其方案数为X), 他里面可能会包含 形如[..., (L个1)](假设其方案数为X1), 注意 不存在末尾有>L个1的情况(因为DP定义里规定了方案的连续长度都是<=L的);
因此 关键是求出X1, 这样X - X1的方案 就是形如[..., p=1, 1]的合法方案了;
. 这也不难, [..., (L个1)],他的方案数 等于[...]里以0结尾的, 即形如[..., 0, (L个1)];

其实你只要想到 X - X1, 即把非法的方案给去除掉,即在DP的前提下 再配合组合问题来优化, 这题就不难;
还有难点 就是很多边界判断/下标越界等 很容易出错, 参见代码把…

int numberOfStableArrays(int Z, int O, int L){
    using Mod_ = ___Modulo_<int, int(1e9) + 7>;
    static Mod_ DP[ 2003][ 1003][ 2];
    FOR_( i, 0, Z+O-1){ FOR_( j, 0, O){ FOR_( k, 0, 1){ DP[i][j][k] = 0;}}}
    DP[0][0][0] = 1;
    DP[0][1][1] = 1;
    FOR_( i, 1, Z+O-1){
        FOR_( j, 0, O){ // `j`是枚举`[0...i]`里`1`的个数 (不是`[0...(i-1)]`里面的)
        	//> 这里很重要, 他保证了 你此时的`(i,j)`是合法的(即里面`1,0`的个数 都是合法的);
            if( (i+1-j)<0 || (i+1-j)>Z){ continue;}

			//> 注意要特判, 即保证`0`的个数是`>=1`的;
            if( i+1-j >= 1){ // [...][0]
                auto & curDP = DP[i][j][0];
                curDP = 0;
                curDP += DP[ i-1][j][1]; // [...1][0]
                
                curDP += DP[ i-1][j][0]; // [...0][0] (他里面包含了非法方案 下面要去除掉)
                int count = i+1 - j; // `[0...i]`中 `0`的个数;
                if( count > L){ // 此时说明 `[...0][0]`里面 有非法方案 即`[... (L个0)][0]`;
                    ASSERTsystem_( i - L-1 >= -1); // 表示`...`的末尾元素下标;
                    if( i - L-1 == -1){ // 此时是`[L个0][0]`;
                        curDP -= 1;
                    }
                    else{                            
                        // curDP -= DP[ i - L-1][ j][0]; // 这是错误的;
                        curDP -= DP[ i - L-1][ j][1];
                    }
                }
            }
			//> 注意要特判, 即保证`1`的个数是`>=1`的;
            if( j >= 1){ // [...][1]
                auto & curDP = DP[i][j][1];
                curDP = 0;
                curDP += DP[ i-1][ j-1][0]; // [...0][1]  (注意是`j-1`)
                
                curDP += DP[ i-1][ j-1][1]; // [...1][1]  (注意是`j-1`)
                int count = j; // `[0...i]`中 `1`的个数; (写成`count=j+1`是错误的)
                if( count > L){ // 此时说明 `[...1][1]`里面 有非法方案 即`[... (L个1)][1]`;
                    ASSERTsystem_( i - L-1 >= -1); // 表示`...`的末尾元素下标;
                    if( i - L-1 == -1){ // 此时是`[L个1][1]`;
                        curDP -= 1; 
                    }
                    else{
                        curDP -= DP[ i - L-1][ j - L-1][0];
                        // curDP -= DP[ i - L-1][ j - L-1][1];  // 这是错误的;
                    }
                }
            }
        }
    }
    return (DP[ Z+O-1][ O][ 0] + DP[ Z+O-1][ O][ 1]).Value;
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Java中,可以使用ImageIO类读取图片文件并将其转换为二进制。下面是一个示例代码: ```java import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; public class ImageToBinary { public static void main(String[] args) { try { // 读取图片文件 File file = new File("image.jpg"); BufferedImage image = ImageIO.read(file); // 将图片转换为二进制 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", baos); baos.flush(); byte[] imageInByte = baos.toByteArray(); baos.close(); // 输出二进制 for (byte b : imageInByte) { System.out.print(b); } } catch (IOException e) { e.printStackTrace(); } } } ``` 上面的代码将读取一个名为"image.jpg"的图片文件,然后使用ImageIO.write()方法将其转换为二进制,并使用ByteArrayOutputStream存储。最后,通过遍历存储二进制的字节数组并输出每个字节来输出二进制。 注意,上面示例代码中读取的是jpg格式图片,如果是其他格式图片请对应修改。 ### 回答2: 要将Java中的图片转换为二进制并输出,可以使用Java提供的BufferedImage和File类进行操作。 首先,需要使用ImageIO类的read方法将图片文件加载到内存中,得到一个BufferedImage对象,如下所示: BufferedImage image = ImageIO.read(new File("图片文件路径")); 接下来,可以使用ByteArrayOutputStream类将BufferedImage对象转换为二进制据,如下所示: ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", baos); baos.flush(); byte[] binaryData = baos.toByteArray(); baos.close(); 在这里,我们以jpg格式为例进行转换,可以根据实际情况选择合适的格式。 最后,将二进制据输出到文件或进行其他操作,如下所示: FileOutputStream fos = new FileOutputStream("输出文件路径"); fos.write(binaryData); fos.close(); 这样就成功将Java中的图片转换为二进制,并输出到指定的文件中。 需要注意的是,上述代码可能会抛出IOException,需要进行异常处理或抛出给调用者处理。 总结起来,将Java图片转换为二进制并输出的步骤如下: 1. 使用ImageIO类的read方法将图片文件加载到内存中,得到BufferedImage对象。 2. 使用ByteArrayOutputStream类将BufferedImage对象转换为二进制据。 3. 将二进制据输出到文件或进行其他操作。 希望能对您有所帮助! ### 回答3: 在Java中将图片转换成二进制并输出的方法有很多,以下是一个简单的示例代码: ```java import java.io.*; import java.nio.file.Files; public class ImageToBinaryConverter { public static void main(String[] args) { String imagePath = "path_to_image_file.jpg"; // 替换为实际的图片文件路径 try { // 读取图片文件 File imageFile = new File(imagePath); byte[] imageBytes = Files.readAllBytes(imageFile.toPath()); // 输出二进制据 FileOutputStream fos = new FileOutputStream("output_binary_file.txt"); // 替换为实际的输出文件路径及文件名 fos.write(imageBytes); fos.close(); System.out.println("图片已成功转换为二进制并输出到文件。"); } catch (FileNotFoundException e) { System.out.println("找不到图片文件。"); e.printStackTrace(); } catch (IOException e) { System.out.println("读取或输出文件时发生错误。"); e.printStackTrace(); } } } ``` 以上代码首先指定了图片文件的路径,然后通过`Files.readAllBytes()`方法将图片文件读取为`byte[]`数组,接着使用`FileOutputStream`将二进制据输出到指定文件中。请确保替换代码中的`imagePath`和输出文件路径及文件名为实际的值。执行代码后,图片将成功转换为二进制据并输出到指定的文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值