近似排列计数

来源:互联网 发布:修改图片的软件 编辑:程序博客网 时间:2024/06/05 09:36

传送
觉得应该可以过三十分的dfs,实际却只过了50…

#include<iostream>#include<cstdio>#include<string>#include<cmath>#include<cstring> #define LL long long#define MOD 1000000007using namespace std;int n,m,k,T,a[100],r,q[100];int ans;bool f[100];void dfs(int x){    if(x==r+1)    {        ans=(ans+1)%MOD;        return;    }    if(q[x]-k>=1)      if(!f[q[x]-k])      {         f[q[x]-k]=1;         dfs(x+1);         f[q[x]-k]=0;         return;      }     for(int i=max(q[x]-k,1);i<=min(q[x]+k,n);i++)      if(!f[i]){        f[i]=1;        dfs(x+1);        f[i]=0;    }}int main(){    scanf("%d",&T);    while(T--)    {        memset(a,0,sizeof(a));        memset(f,0,sizeof(f));        r=0;ans=0;        scanf("%d%d%d",&n,&m,&k);        for(int i=1;i<=m;i++)        {            int x,y;            scanf("%d%d",&x,&y);            a[x]=y;f[y]=1;        }        for(int i=1;i<=n;i++) if(!a[i]) q[++r]=i;        dfs(1);        printf("%d\n",ans);    }    return 0;}

理论上可以过50的dp

#include<iostream>#include<cstring>#include<string>#include<cmath>#include<algorithm>#include<cstdio> #define MOD 1000000007#define LL long longusing namespace std;int maxn,n,m,k,now; int T,a[100];int dp[(1<<21)];int dx[]={0,-1,0,1,-2,2},r; int main(){    //freopen("a.in","r",stdin);    //freopen("a.out","w",stdout);    scanf("%d",&T);    while(T--)    {        memset(a,0,sizeof(a));        memset(dp,0,sizeof(dp));        scanf("%d%d%d",&n,&m,&k);        maxn=(1<<n)-1;        for(int i=1;i<=m;i++)        {            int x,y;            scanf("%d%d",&x,&y);            a[x]=y;        }        if(k==0) {printf("1\n");continue;}        if(k==1) r=3;        if(k==2) r=5;        dp[0]=1;        for(int i=1;i<=n;i++)        {            if(a[i])            {                for(int j=maxn;j>=0;j--)                  if(!(j&(1<<(a[i]-1)))) dp[j|(1<<a[i]-1)]=(dp[j]+dp[j|(1<<a[i]-1)])%MOD;            }            else            {                for(int j=maxn;j>=0;j--)                  for(int s=1;s<=r;s++)                  {                      int x=i+dx[s];                      if(x<1||x>n) continue;                      if(!(j&(1<<x-1))) dp[j|(1<<x-1)]=(dp[j|(1<<x-1)]+dp[j])%MOD;                  }            }        }        printf("%d\n",dp[maxn]);    }    return 0;}