题目: Petya and Spiders
传送门:
http://codeforces.com/problemset/problem/111/C
http://codeforces.com/problemset/problem/112/E
分析:
(1)由n·m<=40可以想到状态压缩动态规划,方程很好想,用四进制表示状态,用位运算优化。
(2)由n·m<=40可以想到分类构造公式。
代码:
1)
#include<cstdio> #include<algorithm> #define inf 2147483647 int n,m,statenum; int num[5000],f[2][5000]; bool pd(int state1,int state2){ int a1=state1%4,b1=0,c1=0,a2=state2%4,b2=0,c2=0; state1/=4;state2/=4; for(int i(1);i<=2*n;i+=2){ c1=b1;b1=a1;a1=state1%4;state1/=4; c2=b2;b2=a2;a2=state2%4;state2/=4; if(b2==0 && b1!=2)return false; if(b1==1 && b2!=2)return false; if(b1==3 && a1!=2 && c1!=2)return false; } return true; } void solve(){ statenum=(1<<n*2)-1; for(int i(0);i<=statenum;++i) {f[0][i]=inf;for(int j=i;j;j>>=2)num[i]+=(j&3)==2;} f[0][statenum]=0; int x=0,y=1; for(int k(1);k<=m+1;++k,x=!x,y=!y) for(int i(0);i<=statenum;++i){ f[y][i]=inf; for(int j(0);j<=statenum;++j) if(f[x][j]!=inf && pd(i,j)) f[y][i]=std::min(f[y][i],f[x][j]+num[i]); } if(f[y][0]==inf) printf("0");else printf("%d",n*m-f[x][0]); } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d %d",&n,&m); if(n>m)std::swap(n,m); solve(); //fclose(stdin);fclose(stdout); return 0; }
2)
#include<cstdio> #define P(x) return printf("%d ",m*n-(x)),0; int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n,m; scanf("%d%d",&n,&m); if(n>m)n^=m,m^=n,n^=m; switch(n){ case 1:P((m+2)/3) case 2:P((m+2)/2) case 3:P(m/4*3+(m%=4)+(m==0)) case 4:P(m+(m==5||m==6||m==9)) case 5:P(m/5*6-(m==7)+(m%=5)+1+(m>1)) case 6:P(10) } fclose(stdin);fclose(stdout); }