spoj 423 Assignments

本文探讨了一种从记忆化搜索优化到状态DP的问题解决策略。面对学生与主题的匹配问题,在限定条件下寻找所有可行解的数量。通过状态压缩与动态规划实现高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:

有N个学生,N个主题。每个学生喜欢N个主题里面的某些主题。(N<=20)

问有多少种选法可以让每个学生都学到自己喜欢的主题。


用记忆化搜索会超时到死的。毕竟操作系统对于递归会不断进行入栈出栈操作,状态dp才是正解。

#include <stdio.h>
#include <string.h>
#include <algorithm>

#define MAXN 20
#define LL long long

using namespace std;

int p[MAXN+1][MAXN];
int l[MAXN+1][190000], sz[MAXN+1];
LL f[2][1<<MAXN];

int main()
{
    int maxs,s,t;
    int i,j,k;
    int ind1,ind2;
    int cas, n, up=1<<MAXN;
    for (int i=0; i<up; ++i)
    {
        int cnt=0;
        for (j=i; j; j>>=1)
           if (j&1) ++cnt;
        l[cnt][sz[cnt]++]=i;
    }
    scanf("%d", &cas);
    while (cas--)
    {
        scanf("%d", &n);
        for (i=1; i<=n; ++i)
            for (j=0; j<n; ++j)
                scanf("%d", &p[i][j]);

        ind1=0;
        ind2=1;
        f[0][0]=1;
        for (i=1,maxs=1<<n; i<=n; ++i)
        {
            for (j=0,s=l[i][j]; j<sz[i]&&l[i][j]<maxs; s=l[i][++j])
            {
                f[ind2][s]=0;
                for (k=0,t=1; k<n; ++k,t<<=1)
                    if (p[i][k]&&(s&t)) f[ind2][s]+=f[ind1][s^t];
            }
            ind2=!ind2;
            ind1=!ind1;
        }
        printf("%lld\n", f[ind1][(1<<n)-1]);
    }
    return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值