解题:2018九省联考 一双木棋

题面

我的常数可能是没救了,明明写的差不多,别人的都跑的飞快,就我的T到爆炸,卡常也卡不过去QAQ

我当初这个题手动讨论拿了25pts,然后胡乱贪心搞了5pts 2333

还以为min-max对抗搜索是什么高端的东西,其实就是记录一下行动方,然后对应的在决策时取min/max

这个题可以证明状态量只有三十多万,于是加上一个记忆化就好了,大概可以状压,也可以哈希+map(我感觉我该写状压的,map不开O2慢的爆炸......)

// luogu-judger-enable-o2
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=12,bas=11,inf=1e9;
int c[N][N],f[N][N],last[N],n,m;
map<long long,int> mp;
inline long long Ghash()
{
    long long hsh=0;
    for(int i=1;i<=n;i++)
        hsh=hsh*bas+last[i];
    return hsh;
}
inline int maxi(int a,int b)
{
    return a>b?a:b;
}
inline int mini(int a,int b)
{
    return a<b?a:b;
}
inline int dosth(long long s)
{
    int ret=0;
    for(int i=n;i;i--)
        last[i]=s%bas,s/=bas,ret+=last[i];
    return ret&1;
}
int DFS(long long s)
{
    if(mp.find(s)!=mp.end()) 
        return mp[s];
    int mov=dosth(s),noww=mov?inf:-inf;
    for(int i=1;i<=n;i++)
        if(last[i]<last[i-1])
        {
            last[i]++;
            long long news=Ghash();
            noww=mov?mini(noww,DFS(news)-c[i][last[i]]):
                     maxi(noww,DFS(news)+f[i][last[i]]);
            last[i]--;
        }
    return mp[s]=noww;
}
int main ()
{
    register int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
         for(j=1;j<=m;j++)
            scanf("%d",&f[i][j]);
    for(i=1;i<=n;i++)
         for(j=1;j<=m;j++)
            scanf("%d",&c[i][j]);
    for(i=0;i<=n;i++) last[i]=m;
    DFS(mp[Ghash()]=0),printf("%d",mp[0]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9794927.html