bzoj5248(洛谷4363)(2018九省联考)一双木棋

题目:https://www.luogu.org/problemnew/show/P4363

一种考虑状态数的方法:有几个用了k个格子的列,就在第k个0的左边插入几个1;

  这也是求不降序列的个数的方法。本题中这样一看,一共有C(10,20)个状态。*m得出记忆化搜索的时间复杂度是18e6左右。

利用hash和map记忆化搜索。那个dg可以设成全局变量,每次复原一下,就不用专门解hash了。之所以还要记s是为了记忆化搜索作角标。

其实这个代码只能在bzoj上A,洛谷上会超时。不超时的方法似乎是轮廓线dp之类。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#define ll long long
using namespace std;
const ll INF=2e8;
int n,m,tot,base,dg[15];
ll a[2][15][15];
map<ll,ll> dp;
map<ll,bool> vis;
ll pw(ll a,int ct)
{
    ll ret=1;
    while(ct)
    {
        if(ct&1)ret*=a;
        a*=a;ct>>=1;
    }
    return ret;
}
ll dfs(ll s,bool k)
{
    if(vis[s])return dp[s];
    vis[s]=1;ll ret=-INF;
//    ll ts=s;
//    int dg[15]={0};
//    for(int i=1;i<=m;i++)dg[i]=ts%base,ts/=base;
    if(dg[m]==n)return 0;
    for(int i=1;i<=m;i++)
        if((i==1&&dg[i]<n)||dg[i-1]>dg[i])
        {
            dg[i]++;
            ret=max(ret,a[k][dg[i]][i]-dfs(s+pw(base,i-1),!k));
            dg[i]--;
        }
    return dp[s]=ret;
}
int main()
{
    scanf("%d%d",&n,&m);base=n+1;
    for(int k=0;k<=1;k++)for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lld",&a[k][i][j]);
    printf("%lld",dfs(0,0));
    return 0;
}

 

转载于:https://www.cnblogs.com/Narh/p/9164002.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值