周伟的论文没能看懂感觉挺羞愧的然而现在我也没能理解。然后滚去看黑书,P138
首先我们先没枚举上一行的状态,dfs这一行的状态,用三进制来表示从上向下有连续的多少个0,然后我们就可以愉快地转移了。
虽然仅仅用时1266ms,但是我并没有明白为什么会这么快,原本以为会T的很惨的。
显然我们先枚举行,然后枚举上一行状态。此时极限数据会达到150*50000+*50000+,然后又5组数据……根本看不到希望
不过实际上会因为这一行很多不能放的和之前的限制把后面的50000+降低了非常多= =,感觉放到UOJ上绝对被hack狂魔折磨的不成人形
周伟的做法dfs同时枚举上一次的状态和这一次的状态,跑的会快很多,然而还没看懂= =
Problem: 1038 User: BPM136 Memory: 1160K Time: 1266MS Language: G++ Result: Accepted #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) #define down(i,a,b) for(int i=a;i>=b;i--) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define N 155 #define M 15 #define K 60000 int f[K][2]; bool map[N][M]; int b[M],s[M]; int n,m,nm; int x,y; void init() { memset(map,0,sizeof(map)); memset(f,-1,sizeof(f)); } void chu() { b[0]=1; fo(i,1,10)b[i]=b[i-1]*3; } void dfs(int xu,int t,int k,int cnt,int num) { if(k>m) { f[cnt][xu&1]=max(f[cnt][xu&1],f[t][(xu-1)&1]+num); return; } int tt=0; if(map[xu][k])tt=2; else if(s[k])tt=s[k]-1;else tt=0; dfs(xu,t,k+1,cnt+tt*b[k-1],num); if(k+1<=m&&s[k]==0&&s[k+1]==0&&!map[xu][k]&&!map[xu][k+1]) dfs(xu,t,k+2,cnt+2*b[k-1]+2*b[k],num+1); if(k+2<=m&&s[k]<=1&&s[k+1]<=1&&s[k+2]<=1) if(!map[xu][k]&&!map[xu][k+1]&&!map[xu][k+2]) dfs(xu,t,k+3,cnt+2*b[k-1]+2*b[k]+2*b[k+1],num+1); } int main() { chu(); int ttt=read(); while(ttt--) { init(); n=read(),m=read(),nm=read(); fo(i,1,nm) { x=read(),y=read(); map[x][y]=1; } f[b[m]-1][0]=0; fo(i,1,n) { fo(j,0,b[m]-1)f[j][i&1]=-1; fo(j,0,b[m]-1) if(f[j][(i-1)&1]!=-1) { s[0]=1; for(int t=j,k=1;k<=m;t/=3,k++)s[k]=t%3; dfs(i,j,1,0,0); } } int ans=-1; fo(i,0,b[m]-1)ans=max(ans,f[i][n&1]); printf("%d\n",ans); } return 0; }