A. CUT RIBBON(暴力枚举或者完全背包)

http://www.yyycode.cn/index.php/2020/05/23/a-cut-ribbon/


https://codeforces.com/problemset/problem/189/A

Polycarpus has a ribbon, its length is n. He wants to cut the ribbon in a way that fulfils the following two conditions:

  • After the cutting each ribbon piece should have length ab or c.
  • After the cutting the number of ribbon pieces should be maximum.

Help Polycarpus and find the number of ribbon pieces after the required cutting.Input

The first line contains four space-separated integers nab and c (1 ≤ n, a, b, c ≤ 4000) — the length of the original ribbon and the acceptable lengths of the ribbon pieces after the cutting, correspondingly. The numbers ab and c can coincide.Output

Print a single number — the maximum possible number of ribbon pieces. It is guaranteed that at least one correct ribbon cutting exists.ExamplesinputCopy

5 5 3 2

outputCopy

2

inputCopy

7 5 5 2

outputCopy

2

Note

In the first example Polycarpus can cut the ribbon in such way: the first piece has length 2, the second piece has length 3.

In the second example Polycarpus can cut the ribbon in such way: the first piece has length 5, the second piece has length 2.


题意:有长度为n的绳子,用长度为a,b,c的小绳子去拼,问用到最多的绳子段数是多少.

思路:做之前看到dp,想到割绳子,但是没想出怎么定义dp状态,于是写了dfs,直接在第5个样例TLE,4000 1 2 3 ;

TLE:

#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e5;
typedef long long LL;
LL res;
LL n,a,b,c;
void dfs(LL length,LL sum)//length表示目前枚举到的长度, sum表示绳子数量
{
//	cout<<"目前枚举到的长度:"<n) return;
	if(length==n)
	{
		res=max(res,sum);return;	
	}	
	dfs(length+a,sum+1);
	dfs(length+b,sum+1);
	dfs(length+c,sum+1);
} 
int main(void)
{
	cin>>n>>a>>b>>c;
	res=-1;
	dfs(0,0);
	cout<

然后呢?n^2暴力枚举叭..p*a+k*b+f*c==n,对p,k,进行枚举,f进行判断,就可以过啦

#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e5;
typedef long long LL;

int main(void)
{
	LL n,a,b,c;cin>>n>>a>>b>>c;
	LL res=-1;
	for(LL i=0;i<=n/a;i++)
		for(LL j=0;i*a+j*b<=n;j++)
		{
			if(  (n-a*i-b*j )%c==0 )
			{
				res=max(res,(i+j+(n-(a*i)-(b*j))/c) );	
			}
		}
	cout<

但是,这个dp怎么写呢?

对于每个绳子,都有取和不取,并且不做限制,是个完全背包问题.

完全背包的二维是dp[i][j]=max(dp[i-1][j],dp[i][j-v[i]]+w[i]);

然后我搞二维的,大晚上的debug了一小时多还没找出来..

搞一维的叭。注意要初始化-1.为什么呢。因为这个题意是要求背包填满的,不初始化的话填的只是背包的价值最大的。

AC:代码

#include
#include
#include
#include
#include
using namespace std;
const int maxn=4040;
#define LL int
//typedef long long LL;
LL f[maxn];
LL d[maxn];
int main(void)
{
	LL n,a,b,c;cin>>n>>a>>b>>c;
	d[1]=a;d[2]=b;d[3]=c;
	memset(f,-0x3f,sizeof(f));
	//for(LL i=1;i<=n;i++) f[i][0]=0;	
	f[0]=0;
//	for(LL j=1;j<=n;j++) f[j][j]=1;
	for(LL i=1;i<=3;i++)///前i个物品 
		for(LL j=d[i];j<=n;j++)///总体积 
			{
			    
				f[j]=max(f[j],f[j-d[i]]+1);
	//	        cout<<"f["<

二维的目前还奇奇怪怪的代码,我以为是memset二维的锅,确实在网上看到有人 说不要用.然后改了for。 这个样例:918 102 1327 1733却输出0…

wa的代码,等待有缘人…

#include
#include
#include
#include
#include
using namespace std;
const int maxn=4040;
#define LL int
//typedef long long LL;
LL f[maxn][maxn];
LL d[maxn];
int main(void)
{
	LL n,a,b,c;cin>>n>>a>>b>>c;
	d[1]=a;d[2]=b;d[3]=c;
//	memset(f,-99,sizeof(f));
    for(LL i=1;i<=maxn;i++)
        for(LL j=1;j<=maxn;j++)
            f[i][j]=-10;
	for(LL i=1;i<=n;i++) f[i][0]=0;	
	f[0][0]=0;
//	for(LL j=1;j<=n;j++) f[j][j]=1;
	for(LL i=1;i<=3;i++)///前i个物品 
		for(LL j=d[i];j<=n;j++)///总体积 
			{
			    
				f[i][j]=max(f[i-1][j],f[i][j-d[i]]+1);
	//	        cout<<"f["<

你可能感兴趣的:(dp,#,codeforces)