CoderForce 189A 割丝带(DP)

链接:click here

题意:

题目是给你一个多长的丝带,然后你要分成几段,且每段的长度必须满足等于a或者b或者c求这个最大的段数
思路:
比赛做完搜一下题解都说是DP ,自己当时做的时候没有想到用DP,写了一个暴力循环,幸运的过了,想转移方程,死磕了一下午,
还是没有搞出个所以然来,虽然代码不过20几行,先贴上标程,以后回过头来在好好想想

代码:

 
//暴力写法:
int main()                    //二成循环, 枚举a和b的段数然后推出c的段数 , 复杂度为O(n^n)
{
    int n,a,b,c,i,j,t,sum=0;
    while(~scanf("%d%d%d%d",&n,&a,&b,&c))
    {
        for(i=0; i*a<=n; i++)
        {
            for(j=0; i*a+j*b<=n; j++)
            {
                if((n-i*a-j*b)%c==0&&(n-i*a-j*b)/c+i+j>sum)
                {
                    sum=(n-i*a-j*b)/c+i+j;
                }
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}

其他写法:

/*dp[i]表示长度为i的ribbon可以分成的最大份数。
<初始状态> dp[0]=0,dp[i]==-1000000表示长度i不可分为a,b,c。
<状态转移> 若i可分,则(i-a),(i-b),(i-c)中至少有一个可分。
dp[i] = max{dp[i-a]+1,dp[i-b]+1,dp[i-c]+1}
*/
从1推到n,dp[n]就是答案了
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <iostream>
#include <string>
#include <string.h>
#include <set>
#include <map>
using namespace std;
int dp[4010];
int n, a, b, c;
int Inf=-0x3f3f3f;
int main ()
{
    cin>>n>>a>>b>>c;
    dp[0]=0;
    for(int i=1; i<=n; i++)
    {
        dp[i]=Inf;
        if(i-a>=0)
            dp[i]=max( dp[i], dp[i-a]+1);
        if(i-b>=0)
            dp[i]=max( dp[i], dp[i-b]+1);
        if(i-c>=0)
            dp[i]=max( dp[i], dp[i-c]+1);
    }
    cout<<dp[n]<<endl;
}




 
 

你可能感兴趣的:(动态规划,ACM)