2012-C17-team5
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
Rank 2,被上交的 JB + SJB + GXX 队踩了,其实这个排名已经相当不错了
附:1008 代码,懒得说明了,有问题直接问我吧
{{{
#include <cstdio>
#include <queue>
#include <cstring>
#include <cassert>
#include <map>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
const int SIZE = 12, INF = 1000000007;
map<int,int> idx;
int at[41836],w;
int go[41836][12];
int ty[41836][12];
int pt[41836][12];
int dp[2][37][41836];
queue<PII> qu[2];
inline int get(int mask, int i){
return (mask>>(i+i))&3;
}
inline void set(int& mask, int i, int v){
mask&=~(3<<(i+i));
mask|= v<<(i+i);
}
inline void relax(int now, int k, int s, int cnt){
if(k>w || s==41835) return;
if(~dp[now][k][s]){
dp[now][k][s]+=cnt;
if(dp[now][k][s]>=INF) dp[now][k][s]-=INF;
}else{
dp[now][k][s]=cnt;
qu[now].push(PII(k,s));
}
}
void build(int mask){
if(idx.count(mask)) return;
at[idx.size()]=mask;
idx.insert(PII(mask,idx.size()));
for(int i=0;i<=SIZE;i++) if(!get(mask,i))
for(int j=i+1;j<=SIZE;j++){
if(get(mask,j)) break;
build(1<<(i+i)|2<<(j+j)|mask);
}
}
void init(){
build(0);
for(int i=0;i<SIZE;i++) go[41835][i]=pt[41835][i]=41835;
for(int s=0;s<41835;s++){
for(int i=0;i<SIZE;i++){
int mask=at[s],z=0;
int x=get(mask,i);
int y=get(mask,i+1);
for(int o=i+1;o<=SIZE;o++) z|=get(mask,o);
pt[s][i]=z?41835:idx[mask<<2];
if(x==1 && y==2){
int cnt=0,v[]={0,+1,-1};
for(int o=0;o<i;o++) cnt+=v[get(mask,o)];
if(cnt&1){
go[s][i]=41835;
}else{
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
ty[s][i]=1;
}
}else if(x==2 && y==1){
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x==1 && y==1){
int cnt=1,v[]={0,+1,-1},o=i+1;
while(cnt) cnt+=v[get(mask,++o)];
set(mask,o,1);
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x==2 && y==2){
int cnt=1,v[]={0,-1,+1},o=i;
while(cnt) cnt+=v[get(mask,--o)];
set(mask,o,2);
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x){
set(mask,i,0);
set(mask,i+1,x);
go[s][i]=idx[mask];
ty[s][i]=2;
}else if(y){
set(mask,i,y);
set(mask,i+1,0);
go[s][i]=idx[mask];
ty[s][i]=2;
}else{
set(mask,i,1);
set(mask,i+1,2);
go[s][i]=idx[mask];
ty[s][i]=4;
}
}
}
}
int main(){
init();
int cs;
scanf("%d",&cs);
while(cs--){
char a[15][15];
int n,m,now=1,ans=0;
scanf("%d%d%d",&n,&m,&w);
memset(dp,-1,sizeof(dp));
qu[0]=qu[1]=queue<PII>();
qu[0].push(PII(0,0));
dp[0][0][0]=1;
for(int i=0;i<n;i++) scanf("%s",a[i]);
if(w>=37){ puts("0");continue; }
for(int i=0;i<n;i++) for(int j=0;j<m;j++){
int h=((n-i)*m-j+1)/4+3;
#define BEGIN while(qu[ans].size()){ \
int k=qu[ans].front().first; \
int s=qu[ans].front().second; \
int cnt=dp[ans][k][s]; \
dp[ans][k][s]=-1; \
qu[ans].pop(); \
if(!cnt || k+h<w) continue;
#define END }
if(j+1==m){
if(a[i][j]=='*') BEGIN
if(ty[s][j]==4) relax(now,k,pt[s][j],cnt);
END else BEGIN
if(ty[s][j]==2) relax(now,k,pt[s][j],cnt);
relax(now,k+(ty[s][j]&1),pt[go[s][j]][j],cnt);
END
}else{
if(a[i][j]=='*') BEGIN
if(ty[s][j]==4) relax(now,k,s,cnt);
END else BEGIN
if(ty[s][j]==2) relax(now,k,s,cnt);
relax(now,k+(ty[s][j]&1),go[s][j],cnt);
END
}
swap(now,ans);
}
printf("%d\n",max(dp[ans][w][0],0));
}
}
}}}
Rank 2,被上交的 JB + SJB + GXX 队踩了,其实这个排名已经相当不错了
附:1008 代码,懒得说明了,有问题直接问我吧
#include <cstdio>
#include <queue>
#include <cstring>
#include <cassert>
#include <map>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
const int SIZE = 12, INF = 1000000007;
map<int,int> idx;
int at[41836],w;
int go[41836][12];
int ty[41836][12];
int pt[41836][12];
int dp[2][37][41836];
queue<PII> qu[2];
inline int get(int mask, int i){
return (mask>>(i+i))&3;
}
inline void set(int& mask, int i, int v){
mask&=~(3<<(i+i));
mask|= v<<(i+i);
}
inline void relax(int now, int k, int s, int cnt){
if(k>w || s==41835) return;
if(~dp[now][k][s]){
dp[now][k][s]+=cnt;
if(dp[now][k][s]>=INF) dp[now][k][s]-=INF;
}else{
dp[now][k][s]=cnt;
qu[now].push(PII(k,s));
}
}
void build(int mask){
if(idx.count(mask)) return;
at[idx.size()]=mask;
idx.insert(PII(mask,idx.size()));
for(int i=0;i<=SIZE;i++) if(!get(mask,i))
for(int j=i+1;j<=SIZE;j++){
if(get(mask,j)) break;
build(1<<(i+i)|2<<(j+j)|mask);
}
}
void init(){
build(0);
for(int i=0;i<SIZE;i++) go[41835][i]=pt[41835][i]=41835;
for(int s=0;s<41835;s++){
for(int i=0;i<SIZE;i++){
int mask=at[s],z=0;
int x=get(mask,i);
int y=get(mask,i+1);
for(int o=i+1;o<=SIZE;o++) z|=get(mask,o);
pt[s][i]=z?41835:idx[mask<<2];
if(x==1 && y==2){
int cnt=0,v[]={0,+1,-1};
for(int o=0;o<i;o++) cnt+=v[get(mask,o)];
if(cnt&1){
go[s][i]=41835;
}else{
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
ty[s][i]=1;
}
}else if(x==2 && y==1){
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x==1 && y==1){
int cnt=1,v[]={0,+1,-1},o=i+1;
while(cnt) cnt+=v[get(mask,++o)];
set(mask,o,1);
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x==2 && y==2){
int cnt=1,v[]={0,-1,+1},o=i;
while(cnt) cnt+=v[get(mask,--o)];
set(mask,o,2);
set(mask,i,0);
set(mask,i+1,0);
go[s][i]=idx[mask];
}else if(x){
set(mask,i,0);
set(mask,i+1,x);
go[s][i]=idx[mask];
ty[s][i]=2;
}else if(y){
set(mask,i,y);
set(mask,i+1,0);
go[s][i]=idx[mask];
ty[s][i]=2;
}else{
set(mask,i,1);
set(mask,i+1,2);
go[s][i]=idx[mask];
ty[s][i]=4;
}
}
}
}
int main(){
init();
int cs;
scanf("%d",&cs);
while(cs--){
char a[15][15];
int n,m,now=1,ans=0;
scanf("%d%d%d",&n,&m,&w);
memset(dp,-1,sizeof(dp));
qu[0]=qu[1]=queue<PII>();
qu[0].push(PII(0,0));
dp[0][0][0]=1;
for(int i=0;i<n;i++) scanf("%s",a[i]);
if(w>=37){ puts("0");continue; }
for(int i=0;i<n;i++) for(int j=0;j<m;j++){
int h=((n-i)*m-j+1)/4+3;
#define BEGIN while(qu[ans].size()){ \
int k=qu[ans].front().first; \
int s=qu[ans].front().second; \
int cnt=dp[ans][k][s]; \
dp[ans][k][s]=-1; \
qu[ans].pop(); \
if(!cnt || k+h<w) continue;
#define END }
if(j+1==m){
if(a[i][j]=='*') BEGIN
if(ty[s][j]==4) relax(now,k,pt[s][j],cnt);
END else BEGIN
if(ty[s][j]==2) relax(now,k,pt[s][j],cnt);
relax(now,k+(ty[s][j]&1),pt[go[s][j]][j],cnt);
END
}else{
if(a[i][j]=='*') BEGIN
if(ty[s][j]==4) relax(now,k,s,cnt);
END else BEGIN
if(ty[s][j]==2) relax(now,k,s,cnt);
relax(now,k+(ty[s][j]&1),go[s][j],cnt);
END
}
swap(now,ans);
}
printf("%d\n",max(dp[ans][w][0],0));
}
}