zoukankan      html  css  js  c++  java
  • LRJ入门经典-0903切蛋糕305

    试题描述

    如图所示有一个矩形蛋糕,上面划分成了n行m列的网格,一些网格内放着樱桃。现在要根据如下规则切蛋糕:

    1.切开的每一块必须是矩形(包括正方形)

    2.切蛋糕时必须沿着网格线,不能拐弯

    3.切开的每一块蛋糕上有且仅有一个樱桃

    下图是一种切割方法:

    这种方法需要切割的边数为2+4=6

    以下是另一种切割方法:

    这种方法需要切割的边数为3+2=5

    现在给定蛋糕的形状和上面樱桃的分布,要求求出切割边数最少的方案。

    输入
    第一行包含三个正整数n,m和k(1<=n,m<=20),k表示樱桃数量
    以下k行每行包含两个正整数,表示每个樱桃所在的行和列
    输出
    输出最优方案的切割边数
    输入示例
    3 4 3
    1 2
    2 3
    3 2
    输出示例
    5

      思路:明显一个递归,相信各位大佬忧虑的是如何在dfs中储存这个区域,我推荐一个方法,可以int dfs(int x,int y,int w,int h)其中x,y表示左上的点的坐标,而w,h表示这个矩形的    长和宽,再加个记忆化,dp[30][30][30][30];就可以再优化。

      详解见代码注释:

      

    #include<bits/stdc++.h>//万能头文件 
    using namespace std;
    int a[30][30];
    int dp[30][30][30][30];//记忆化搜索的dp 
    int n,m;
    int k;
    int dfs(int x,int y,int w,int h)//dfs函数 
    {
    	int cnt=0;//cnt表示该蛋糕上的樱桃数
    	for(int i=x+1;i<=x+w;i++)
    	{
    		for(int j=y+1;j<=y+h;j++)
    		{
    			if(a[i][j]) cnt++;//统计樱桃数
    		}
    	}
    	if(cnt==0) return 999999999;//如果蛋糕上的樱桃数为0,999999999代表inf 
    	if(cnt==1) return 0;//如果蛋糕上的樱桃数为1,直接return 0 
    	if(dp[x][y][w][h]!=-1) return dp[x][y][w][h];//如果之前搜过,就不用搜了,直接return掉 
    	int ans=2147483647;//ans初值为最大值 
    	for(int i=1;i<w;i++)//搜横行 
    	{
    		ans=min(ans,dfs(x,y,i,h)+dfs(x+i,y,w-i,h)+h);//min一下 
    	}
    	for(int i=1;i<h;i++)//同上 
    	{
    		ans=min(ans,dfs(x,y,w,i)+dfs(x,y+i,w,h-i)+w);
    	}
    	dp[x][y][w][h]=ans;//赋值 
    	return ans;
    }
    int main()
    {
    	memset(dp,-1,sizeof(dp));//给dp赋初值 
    	scanf("%d%d%d",&n,&m,&k);
    	int p,q;
    	for(int i=1;i<=k;i++)
    	{
    		scanf("%d%d",&p,&q);
    		a[p][q]=1;
    	}
    	cout<<dfs(0,0,n,m);//dfs一下 
    	return 0;
    }
    

      

  • 相关阅读:
    Windows10右键添加“在此处打开命令窗口"
    赋值简单理解
    应用 EditPlus 配置 Java 编译环境
    进程和线程的区别
    Java栈与堆
    进程与线程的简单解释
    java的多态性(二)
    内部类详解(很详细)
    java的super和this关键字用法总结
    Java类成员(成员变量和方法)的覆盖与隐藏归纳
  • 原文地址:https://www.cnblogs.com/chen-1/p/9837728.html
Copyright © 2011-2022 走看看