AtCoder Beginner Contest 192 F - Potion 背包dp

传送门

题意: 给你 n n n个数,让后让你选出来 k k k A A A,把他们求和,之后再递增 k k k直到正好达到 x x x,求最小的递增次数。

思路: 转化一下题意就是求 ∑ A = x (   m o d      l e n ) \sum A=x(\bmod\ \ len) A=x(mod  len),且 ∑ A \sum A A最大,考虑如何解决 ∑ A \sum A A最大的问题。
f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示前 i i i个数选了 j j j个且   m o d      l e n \bmod \ \ len mod  len k k k,那么转移就比较明显了: f [ i ] [ j ] [ k ] = m a x ( f [ i − 1 ] [ j ] [ k ] , f [ i − 1 ] [ j − 1 ] [ ( k + l e n − ( a [ i ]   m o d   l e n ) )   m o d   l e n ] ) f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][(k+len-(a[i]\bmod len))\bmod len]) f[i][j][k]=max(f[i1][j][k],f[i1][j1][(k+len(a[i]modlen))modlen])答案就是 m a x ( a n s , ( x − f [ n ] [ l e n ] [ x   m o d   l e n ] ) / l e n ) max(ans,(x-f[n][len][x\bmod len])/len) max(ans,(xf[n][len][xmodlen])/len)

**//#pragma GCC optimize(2)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=210,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n;
LL x,ans=1e18,a[N];
LL f[N][N][N];// 前i个数选j个%len余数为k

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d%lld",&n,&x);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int len=1;len<=n;len++)
    {
        memset(f,-INF,sizeof(f));
        f[0][0][0]=0;
        for(int i=1;i<=n;i++)
        {
            f[i][0][0]=0;
            for(int j=1;j<=len;j++)
                for(int k=0;k<len;k++)
                    f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][(k+len-(a[i]%len))%len]+a[i]);
        }
        if(f[n][len][x%len]>=0) ans=min(ans,(x-f[n][len][x%len])/len);
    }
    printf("%lld\n",ans);


	return 0;
}
/*

*/





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