dp
原本在记忆化搜索时想用hash来判重着,写了一个hash版本ac后,在写解题报告时发现其实不用hash也可,
直接改为记忆化搜索果断ac,没想到这么容易就过了,这题一开始想多了。
这题这么水,实在对不起30s的时限,或许可能存在搜索的版本吧。
164ms
#include <iostream> #include<cstdio> #include<cstring> #define N 41 using namespace std; int n; int dp[N][N][N][N]; int mat[N][4]; int DP(int *top,int st,int k) { int &m=dp[top[0]][top[1]][top[2]][top[3]]; if(m!=-1) return m; if(top[0]==n&&top[1]==n&&top[2]==n&&top[3]==n||k==5) return m=0; for(int i=0;i<4;i++) if(top[i]<n) { int bit=1<<mat[top[i]][i]; top[i]++; if(bit&st) m=max(m,DP(top,st-bit,k-1)+1); else if(k<5) m=max(m,DP(top,st+bit,k+1)); top[i]--; } return m; } int main() { while(scanf("%d",&n),n) { memset(dp,-1,sizeof(dp)); for(int i=0;i<n;i++) for(int j=0;j<4;j++) scanf("%d",&mat[i][j]); int top[5]={0}; printf("%d\n",DP(top,0,0)); } return 0; }
hash 版本 460ms
#include <iostream> #include<cstdio> #include<cstring> #define N 41 #define M 1000000 using namespace std; int n; int dp[N][N][N][N]; int mat[N][4]; int state[10000000][5],next[10000000],head[M],e; int hash(int cur) { int v=0; for(int i=0;i<5;i++) v=v*40+state[cur][i],v%=M; return v; } bool insert(int u) { int h=hash(u); int v=head[h]; while(v!=-1) { if(!memcmp(state[u],state[v],sizeof(state[v]))) return false; v=next[v]; } next[u]=head[h]; head[h]=u; return true; } int DP(int *top,int st,int k) { int &m=dp[top[0]][top[1]][top[2]][top[3]]; if(m!=-1) { top[4]=st; memcpy(state[e],top,sizeof(top)); if(!insert(e)) return m; e++; } if(top[0]==n&&top[1]==n&&top[2]==n&&top[3]==n||k==5) return m=0; for(int i=0;i<4;i++) if(top[i]<n) { int bit=1<<mat[top[i]][i]; top[i]++; if(bit&st) m=max(m,DP(top,st-bit,k-1)+1); else if(k<5) m=max(m,DP(top,st+bit,k+1)); top[i]--; } return m; } int main() { while(scanf("%d",&n),n) { memset(dp,-1,sizeof(dp)); memset(head,-1,sizeof(head)); e=0; for(int i=0;i<n;i++) for(int j=0;j<4;j++) scanf("%d",&mat[i][j]); int top[5]={0}; printf("%d\n",DP(top,0,0)); } return 0; }