记录当前待判断区域的上边界的位置-1、下边界、左边界的位置-1、右边界,减一是为了后面更加方便以及准确地判断。然后查找当前区域中的樱桃的数量,如果数量为0,那么记录当前需要裁剪的长度为无穷大(代表的含义也就是不能够在当前的区域进行进一步地裁剪),如果数量为1,那么记录当前需要裁剪的长度为0,表示当前区域已经满足要求了,不需要进行进一步地裁剪,如果数量大于等于2,那么就在当前区域尝试逐行裁剪以及逐列裁剪,同时比较并且记录裁剪得到的最小值,并返回即可,具体实现见如下代码:
package a;//实际提交的时候记得去掉包名
import java.util.Arrays;
import java.util.Scanner;
public class Main {
int n,m,k;
int [][]area=new int[22][22];
int [][][][]dp=new int[22][22][22][22];
int Case=0;
public void Init(){
for(int i=0;i<22;i++){
Arrays.fill(area[i],0);
}
for(int i=0;i<22;i++){
for(int j=0;j<22;j++){
for(int k=0;k<22;k++){
Arrays.fill(dp[i][j][k],-1);
}
}
}
}
public int amountCherry(int u,int d,int l,int r){
int amount=0;
for(int i=u+1;i<=d;i++){
for(int j=l+1;j<=r;j++){
if(area[i][j]==1){
amount++;
if(amount==2) return amount;
}
}
}
return amount;
}
public int DP(int u,int d,int l,int r){
if(dp[u][d][l][r]!=-1) return dp[u][d][l][r];
int amount=amountCherry(u,d,l,r);
if(amount==1){
dp[u][d][l][r]=0;
return 0;
}
else if(amount==0){
dp[u][d][l][r]=(1<<20);
return dp[u][d][l][r];
}
else{
dp[u][d][l][r]=(1<<20);
for(int i=u+1;i<d;i++){//按照行来剪
dp[u][d][l][r]=Math.min(dp[u][d][l][r],DP(u,i,l,r)+DP(i,d,l,r)+r-l);
}
for(int j=l+1;j<r;j++){//按照列来剪
dp[u][d][l][r]=Math.min(dp[u][d][l][r],DP(u,d,l,j)+DP(u,d,j,r)+d-u);
}
}
return dp[u][d][l][r];
}
public void dealPro(){
Scanner scan=new Scanner(System.in);
while(scan.hasNext()){
Init();
n=scan.nextInt();
m=scan.nextInt();
k=scan.nextInt();
for(int i=0;i<k;i++){
int x=scan.nextInt();
int y=scan.nextInt();
area[x][y]=1;
}
Case++;
System.out.println("Case "+Case+": "+DP(0,n,0,m));
}
}
public static void main(String[] args){
Main a=new Main();
a.dealPro();
}
}
本文介绍了一种用于裁剪包含特定数量樱桃区域的算法。通过记录边界位置并采用动态规划策略,该算法能有效地找到最优裁剪方案。文章提供了完整的Java实现代码。
947

被折叠的 条评论
为什么被折叠?



