1. 程式人生 > >bzoj5248(洛谷4363)(2018九省聯考)一雙木棋

bzoj5248(洛谷4363)(2018九省聯考)一雙木棋

In int CA 超時 tdi .org %d col DG

題目: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; }

bzoj5248(洛谷4363)(2018九省聯考)一雙木棋