noi-openjudge[4.7搜索]怀表问题

时间:2023-03-10 00:09:43
noi-openjudge[4.7搜索]怀表问题

为啥我觉得这是个DP….f[i][j][k][l]表示四种零件分别用了i,j,k,l个的方案数。然后发现这样不能保证表一定能接在表链首尾,也不知道状态之间如何转移,那么加一维变成f[i][j][k][l][S],S表示首尾的状态(4种),于是就可以预处理了。然后我们需要从给出的一共n个4种零件中选出k个。那么dfs暴力枚举方案。

一开始DP求的状态是i,j,k,l四维都取到1-40,算了一些冗余状态,T了……后来限制四维之和小于等于40,A了……不过慢死…好像别人是直接搜的,加个记忆化?因为真正用到的状态数目不多所以会比较快?

#include<cstdio>
typedef long long ll;
ll f[][][][][];//4:首-尾字母
void dp(){//并不是所有状态都会被用到?
f[][][][][]=f[][][][][]=f[][][][][]=f[][][][][]=;
for(int i=;i<=;++i){
for(int j=;i+j<=;++j){
for(int k=;i+j+k<=;++k){
for(int l=;i+j+k+l<=;++l){
if(i+j+k+l==)continue;
for(int s=;s<;++s){
if(i!=&&(s&)==)f[i][j][k][l][s]+=f[i-][j][k][l][s];
if(j!=&&(s&)==)f[i][j][k][l][s]+=f[i][j-][k][l][s^];
if(k!=&&(s&)==)f[i][j][k][l][s]+=f[i][j][k-][l][s^];
if(l!=&&(s&)==)f[i][j][k][l][s]+=f[i][j][k][l-][s];
}
}
}
}
}
}
int cnt[];
int sol[];
ll ans=;int S;
int n,k;
void dfs(int x,int sum){
if(x==){
if(sum==)ans+=f[sol[]][sol[]][sol[]][sol[]][S];
return;
}
for(int i=;i<=cnt[x]&&i<=sum;++i){
sol[x]=i;
dfs(x+,sum-i);
sol[x]=;
} }
int main(){
dp();
char buf[];
while(scanf("%d%d",&n,&k)!=EOF){
scanf("%s",buf);
S=;
if(buf[]=='V')S+=;
if(buf[]=='V')S+=;
cnt[]=cnt[]=cnt[]=cnt[]=;
for(int i=;i<=n;++i){
scanf("%s",buf);
int tmp=;
if(buf[]=='V')tmp+=;
if(buf[]=='V')tmp+=;
cnt[tmp]++;
}
ans=;
dfs(,k); if(ans==)printf("NO\n");
else printf("YES\n%lld\n",ans);
}
return ;
}