切纸术(动归)——锯钢条二维版

本文介绍如何运用动态规划解决实际问题——切割矩形白纸成指定尺寸纸条的最大数量。通过算法实现,作者将生活经验转化为编程解决方案,展示了将数学与计算机科学结合的应用价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

切纸术(动归)——锯钢条二维版


题目:
有一张N*M的矩形白纸,要求切出A*B的纸条若干张,问最多能切出几张!(注:现实中的切纸机一刀必定切断纸,也就是说在切的过程中始终保持纸是矩形的!)

输入
N M A B                           N,M>A,B>0     0<N,M<1000
输出
X(即最多的白纸数)

因为这个题是我生活中碰见的问题,正好因为最近竞赛学了动归,就拿来解一解,没想到还真让我弄出来了,希望看见的大神们改进改进。
我的想法就是经典的动归,先记录我每次能切的步长放入数组b中,然后对横着切b[i],i=0,1,2....或竖着切做决策,方程出来就简单了,这里我因技术不过关,写的是递归,不过加了缓存时间上也差不多和递推一样。


#include <stdio.h>
#define maxc(x,y) ((x)=(x)<(y)?(y):(x))
int buf[2000][2000];
int b[500];
int inl,ink,cutl,cutk;
int bn;
int back(const void * p1,const void * p2)
{
	return (*((int *)p1))-(*((int *)p2));
}
int fun(int l,int k)
{
	int i,j,bi;
	int max;
	if(l*k<cutl*cutk)return 0;
	if(l<cutk||k<cutk)return 0;
	if(k<cutl&&l<cutl)return 0;
	if(l==cutl&&k==cutk)return 1;
	if(l==cutk&&k==cutl)return 1;
	else
	{
		max=0;
		for(bi=1;bi<bn;bi++)
		{
			if(k-b[bi]>0)
			{
				maxc(max,(buf[l][k-b[bi]]?buf[l][k-b[bi]]:fun(l,k-b[bi]))+(buf[l][b[bi]]?buf[l][b[bi]]:fun(l,b[bi])));
			}
			if(l-b[bi]>0)
			{
				maxc(max,(buf[l-b[bi]][k]?buf[l-b[bi]][k]:fun(l-b[bi],k))+(buf[b[bi]][k]?buf[b[bi]][k]:fun(b[bi],k)));
			}
		}
		buf[l][k]=max;
		buf[k][l]=max;
		return max;
	}
	
}
int main(){
	int i,j;
	scanf("%d%d%d%d",&inl,&ink,&cutl,&cutk);
	if(inl<ink)inl^=ink^=inl^=ink;
	if(cutl<cutk)cutl^=cutk^=cutl^=cutk;
	for(i=1;i*cutl<inl;i++)
	{
		b[i]=i*cutl;
		
	}
		for(j=1;j*cutk<inl;i++,j++)
	{
		b[i]=j*cutk;
		
	}
	bn=i;
	qsort(b,bn,4,back);
	printf("%d",fun(inl,ink));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值