P4876 近似排列计数50

时间限制:1s

内存限制:256MB

【问题述】

    对于一个1~n的排列,如果满足第i个数|ai-i|<=k,则称该排列为K-近似排列。

    现在排列的若干位置已经确定,你需要计算剩下的数有多少种排列方法使得形成的排列是K-近似排列。

【输入】

输入文件名为count.in。

第一行一个数T(<=10),表示数据组数

对于每一组数据:

第一行三个数n,m,k,分别表示排列长度、已确定位置的个数和近似参数K

         接下来m行,每行两个数x、y,表示已经确定第x个数是y

【输出】

输出文件名为count.out。

对于每组数据输出一行,包含一个数,表示方法个数(对1,000,000,007取模)

 

【输入输出样例】

count.in

count.out

1

4 1 1

2 3

1

 

【数据说明】

对于30%的数据,1<=n,m<=10,k<=2

对于50%的数据,1<=n,m<=20,k<=2

对于70%的数据,1<=n<=100000,m<=100,k<=2

对于100%的数据,1<=n<=10^9,m<=100,k<=2

坑啊,题目给的样例不对,他写的是2,其实是1.!

小暴力50分

 

复制代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,k,t;
int a[100009];
bool vis[100009];
long long ans;
void dfs(int x)
{        
    if(x==n+1)
    {
        ans++;
        return ;
    }
    if(a[x])    dfs(x+1);
    else 
    {
        if(x>=3)
        if(!vis[x-k])
        {
            vis[x-k]=1;
            dfs(x+1);
            vis[x-k]=0;
            return ;
        }
        
        for(int i=max(x-k,1);i<=min(x+k,n);i++)
        if(!vis[i])
        {
            vis[i]=1;
            dfs(x+1);
            vis[i]=0;
        }
    }
    return ;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) a[i]=0,vis[i]=0;
        ans=0;        
        for(int i=1,x,y;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            a[x]=y;vis[y]=1;
        }
        dfs(1);
        printf("%lld\n",ans);
    }
    return 0;
}
50分暴力
复制代码

 

 也可以用状压dp做

  定义f[j]为当前位上状态为j的方案数,j是一个二进制数,对一每一位上1代表这个数用过,0代表没用过。(其实能用二维的,习惯用一维,有个二维代码)

  对于每个状态,看看能否和    i-k到i+k中每个数拓展,,能拓展的话,就向更大的数扩展。(就是说看看这些数选没选,没选过的话就加过去)。

  

70分还是没写出来。。。

复制代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int P=1000000007;
int f[1<<20],a[100009];
int t,n,m,k;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(a,-1,sizeof(a));
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x--,y--;
            a[x]=y;
        }
        memset(f,0,sizeof(f));
        for(int i=0;i<=k&&i<n;i++)
        {
            if(a[0]!=-1&&a[0]!=i) continue;
            f[1<<i]=1;
        }
        
        for(int i=0;i<n-1;i++)
        for(int j=(1<<n)-1;j>=0;j--)
        {
            if(!f[j])    continue;
            for(int t=max(0,i+1-k);t<=min(n-1,i+1+k);t++)
            {
                if(j>>t&1)    continue;
                if(a[i+1]!=-1&&a[i+1]!=t)    continue;                
                f[j|(1<<t)]=(f[j|(1<<t)]+f[j])%P;
            }
        }        
        printf("%d\n",f[(1<<n)-1]);
        
    }
    return 0;
}
50分状压dp-一维 
复制代码
复制代码
50分DP
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int P=1000000007;
int f[20][1<<20],a[20];
int t,n,m,k;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(a,-1,sizeof(a));
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            x--,y--;
            a[x]=y;
        }
        memset(f,0,sizeof(f));
        for(int i=0;i<=k&&i<n;i++)
        {
            if(a[0]!=-1&&a[0]!=i) continue;
            f[0][1<<i]=1;
        }
        
        for(int i=0;i<n-1;i++)
        for(int j=0;j<(1<<n);j++)
        {
            if(!f[i][j])    continue;
            for(int t=max(0,i+1-k);t<=min(n-1,i+1+k);t++)
            {
                if(j>>t&1)    continue;
                if(a[i+1]!=-1&&a[i+1]!=t)    continue;
                if(abs(t-(i+1))>k)    continue;
                f[i+1][j|(1<<t)]=(f[i+1][j|(1<<t)]+f[i][j])%P;
            }
        }
        
        printf("%d\n",f[n-1][(1<<n)-1]);
        
    }
    return 0;
}
二维
复制代码

 

posted @   浪矢-CL  阅读(318)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示