オリジナルタイトルpress_here!
トピックをオーバープルするのが面倒
問題の解
状態遷移方程式を考えてみます。
\ [Dpは(I)= DP(I-1)+ [a_iをA_1があり、A_2、...、A_ {I-1}何らかの線形結合]、\クワッドI> 1 \]
ここで、角括弧で真である命題である\(1 \) 、そうでなければ\(0 \) 。
そして、メモリ検索
取得する方法について考えた後、暴力的な最終のかナップザック問題にメモリを追加しました......とにかく、AC Guannameduoではありません
式はに減らすことができます。
\ [DP(I)= DP(I-1)+ [!DFS(I-1、a_iを)]、\クワッドI> 1 \]
ここで、dfs(int pos,int rest)
で\(A_ {POS} \)である\(A_1、A_2、...、 A_ {POS-1} \) の特定の線形結合で\(1 \) 、そうでなければ\(0 \)
コード:
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
char c=getchar();int x=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
x=x*10+c-'0';
return x;
}
int n,m,a[105],f[105][25005],dp[105];
bool dfs(int pos,int rest)
{
if(rest==0)return 1;
if(pos==0)return 0;
if (f[pos][rest]!=-1)return f[pos][rest];
bool res=0;
for(int i=0;rest-i*a[pos]>=0;i++)
res|=dfs(pos-1,rest-i*a[pos]);
return f[pos][rest]=res;
}
int main()
{
int T=read();
while(T--)
{
memset(a,0,sizeof(a));
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1);
memset(f,-1,sizeof(f));
memset(dp,0,sizeof(dp));
dp[1]=1;
for(int i=2;i<=n;i++)dp[i]=dp[i-1]+(!dfs(i-1,a[i]));
printf("%d\n",dp[n]);
}
return 0;
}