今天一共四道插头DP【其实都差不多】,智障错误出了不下五个:D
来,让我好好数落我自己一下
直接写代码注释里吧
Eat the Trees
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,m;
int a[
15][
15],sit[
15];
long long f[
15][
15][(
1<<
15)+
10];
//忘开long long几百次
void clear(){
memset(f,0,
sizeof(f));
memset(a,0,
sizeof(a));
}
void work(
int x,
int y){
int plug1=sit[y-
1],plug2=
sit[y];
for(
int i=
0;i<sit[m+
1];i++
){
if(a[x][y]){
f[x][y][i]+=f[x][y-
1][i^plug1^
plug2];
if(((i>>y-
1)&
1)==((i>>y)&
1))
continue;
f[x][y][i]+=f[x][y-
1][i];
}
else{
if(!(i&plug1)&&!(i&plug2))f[x][y][i]=f[x][y-
1][i];
else f[x][y][i]=
0;
}
}
}
int main()
{
scanf("%d",&
t);
sit[0]=
1;
for(
int i=
1;i<=
15;i++)sit[i]=sit[i-
1]<<
1;
while(t--
){
clear();
scanf("%d%d",&n,&
m);
for(
int i=
1;i<=n;i++
){
for(
int j=
1;j<=m;j++
){
scanf("%d",&
a[i][j]);
}
}
f[1][
0][
0]=
1;
for(
int i=
1;i<=n;i++
){
for(
int j=
1;j<=m;j++
){
work(i,j);
}
if(i!=
n){
for(
int j=
0;j<sit[m];j++
){
f[i+
1][
0][j<<
1]=
f[i][m][j];
}
}
}
printf("%lld\n",f[n][m][
0]);
}
return 0;
}
//第一篇几乎是对着前辈的代码打的 大概没什么问题 【虽然本质应该是背着打然后对着改】
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,e1,e2,las,now,tt;
const int has=
299989;
int sit[
15],a[
2][
300005],mp[
15][
15],head[
300005],Next[
300005],tot[
2];
long long f[
2][
300005],ans;
char c[
15];
void ins(
int zt,
long long num){
int pos=zt%has+
1;
for(
int i=head[pos];i;i=
Next[i]){
if(a[now][i]==
zt){
f[now][i]+=
num;
return;
}
}
Next[++tot[now]]=head[pos],head[pos]=
tot[now];
a[now][tot[now]]=zt,f[now][tot[now]]=
num;
}
void work(){
tot[now]=
1,f[now][
1]=
1,a[now][
1]=
0;
for(
int i=
1;i<=n;i++
){
for(
int j=
1;j<=tot[now];j++)a[now][j]<<=
2;
for(
int j=
1;j<=m;j++
){
las=now,now^=
1;
memset(head,0,
sizeof(head));
tot[now]=
0;
for(
int k=
1;k<=tot[las];k++
){
int zt=a[las][k],b1=((zt>>((j-
1)*
2))%
4),b2=((zt>>(j*
2))%
4);
long long num=
f[las][k];
if(!
mp[i][j]){
if(!b1&&!
b2)ins(zt,num);
}
else if(!b1&&!
b2){
if(mp[i+
1][j]&&mp[i][j+
1])ins(zt+sit[j-
1]+
2*
sit[j],num);
}
else if(b1&&!
b2){
if(mp[i][j+
1])ins(zt-sit[j-
1]*b1+sit[j]*
b1,num);
if(mp[i+
1][j])ins(zt,num);
}
else if(!b1&&
b2){
if(mp[i+
1][j])ins(zt-sit[j]*b2+sit[j-
1]*
b2,num);
if(mp[i][j+
1])ins(zt,num);
}
else if(b1==
1&&b2==
1){
int kl=
1;
for(
int t=j+
1;t<=m;t++
){
if((zt>>(t*
2))%
4==
1)kl++
;
if((zt>>(t*
2))%
4==
2)kl--
;
if(!
kl){
ins(zt-sit[j-
1]-sit[j]-
sit[t],num);
break;
}
}
}
else if(b1==
2&&b2==
2){
int kl=
1;
for(
int t=j-
2;t>
0;t--
){
if((zt>>(t*
2))%
4==
1)kl--
;
if((zt>>(t*
2))%
4==
2)kl++
;
if(!
kl){
ins(zt+sit[t]-
2*sit[j-
1]-
2*
sit[j],num);
break;
}
}
}
else if(b1==
2&&b2==
1){
ins(zt-
2*sit[j-
1]-
sit[j],num);
}
else if(i==e1&&j==e2)ans+=
num;
}
}
}
}
int main()
{
scanf("%d%d",&n,&
m);
for(
int i=
1;i<=n;i++
){
scanf("%s",c+
1);
for(
int j=
1;j<=m;j++
){
if(c[j]==
'.')mp[i][j]=
1,e1=i,e2=
j;
}
}
sit[0]=
1;
for(
int i=
1;i<=
12;i++
){
sit[i]=(sit[i-
1]<<
2);
}
work();
printf("%lld\n",ans);
return 0;
}
//其实也是背着写了一遍再对着标程改…这一篇是一次AC【这是个伏笔】
P2289 [HNOI2004]邮递员
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m,n,now,lst;
const int has=
299989;
int sit[
12],a[
2][
300010],head[
300010],Next[
300010],tot[
2];
struct node{
int len;
int c[
50];
}f[2][
300010],ans;
node jia(node a,node b){
node d;
int sum=
0;
memset(d.c,0,
sizeof(d.c));
d.len=
max(a.len,b.len);
for(
int i=
1;i<=d.len;i++
){
sum=sum+a.c[i]+
b.c[i];
d.c[i]=sum%
10;
sum/=
10;
}
while(sum){
d.c[++d.len]=sum%
10;
sum/=
10;
}
return d;
}
void ins(
int zt,node num){
int pos=zt%has+
1;
for(
int i=head[pos];i;i=
Next[i]){
if(a[now][i]==
zt){
f[now][i]=jia(f[now][i],num);
//这个地方写成了jia(f[now][i],num)
//对,不是f[now][i]=jia(f[now][i],num)…只写了调用函数没有赋值…还以为是高精炸了
return;
}
}
Next[++tot[now]]=head[pos],head[pos]=
tot[now];
a[now][tot[now]]=zt,f[now][tot[now]]=
num;
}
void work(){
memset(f[now][1].c,
0,
sizeof(f[now][
1].c));
tot[now]=
1,a[now][
1]=
0,f[now][
1].len=
1,f[now][
1].c[
1]=
1;
for(
int i=
1;i<=n;i++
){
for(
int j=
1;j<=tot[now];j++)a[now][j]<<=
2;
for(
int j=
1;j<=m;j++
){
lst=now,now^=
1;
memset(head,0,
sizeof(head));
tot[now]=
0;
for(
int k=
1;k<=tot[lst];k++
){
node num=
f[lst][k];
int zt=
a[lst][k];
int b1=((zt>>(j-
1)*
2))%
4,b2=(zt>>(j*
2))%
4;
if(!b1&&!
b2){
if(j+
1<=m&&i+
1<=n)ins(zt+sit[j-
1]+sit[j]*
2,num);
}
else if(!b1&&
b2){
if(j+
1<=
m)ins(zt,num);
if(i+
1<=n)ins(zt-sit[j]*b2+sit[j-
1]*
b2,num);
}
else if(b1&&!
b2){
if(i+
1<=
n)ins(zt,num);
if(j+
1<=m)ins(zt-sit[j-
1]*b1+sit[j]*
b1,num);
}
else if(b1==
1&&b2==
1){
int kl=
1;
for(
int t=j+
1;t<=m;t++
){
if((zt>>(t*
2))%
4==
1)kl++
;
if((zt>>(t*
2))%
4==
2)kl--
;
if(!
kl){
ins(zt-sit[j]-sit[j-
1]-
sit[t],num);
break;
}
}
}
else if(b1==
2&&b2==
2){
int kl=
1;
for(
int t=j-
2;t>
0;t--){
//写成j-1一万次……
if((zt>>(t*
2))%
4==
1)kl--
;
if((zt>>(t*
2))%
4==
2)kl++
;
if(!
kl){
ins(zt-sit[j]*
2-sit[j-
1]*
2+
sit[t],num);
break;
}
}
}
else if(b1==
2&&b2==
1){
ins(zt-sit[j-
1]*
2-
sit[j],num);
}
else if(i==n&&j==m)ans=
jia(ans,num);
}
}
}
}
int main()
{
scanf("%d%d",&m,&
n);
if(m==
1||n==
1){
//这个特判,一开始打成m==1||n==1 输出0…然后折腾了半天想路径长度去了【?】 然后写成了m==1&&n==1 输出1…
printf(
"1");
return 0;
}
sit[0]=
1;
for(
int i=
1;i<=
11;i++)sit[i]=(sit[i-
1]<<
2);
//一开始跑了n的范围,20,还没意识到炸了…被提醒以后第一反应居然是开long long而不是转成m的范围
work();
ans=
jia(ans,ans);
if(!
ans.len){
printf("0");
return 0;
}
for(
int i=ans.len;i>=
1;i--
){
printf("%d",ans.c[i]);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,now,lst,e1,e2;
const int has=
299989;
long long ans,f[
2][
300010];
int a[
2][
300010],tot[
2],Next[
300010],head[
300010],sit[
15];
char mp[
15][
15],s[
15];
void ins(
int zt,
long long num){
int pos=zt%has+
1;
for(
int i=head[pos];i;i=
Next[i]){
if(a[now][i]==
zt){
f[now][i]+=
num;
return;
}
}
Next[++tot[now]]=head[pos],head[pos]=
tot[now];
a[now][tot[now]]=zt,f[now][tot[now]]=
num;
}
void work(){
tot[now]=
1,a[now][
1]=
0,f[now][
1]=
1;
for(
int i=
1;i<=n;i++
){
for(
int j=
1;j<=tot[now];j++)a[now][j]<<=
2;
for(
int j=
1;j<=m;j++
){
lst=now,now^=
1;
memset(head,0,
sizeof(head));
tot[now]=
0;
for(
int k=
1;k<=tot[lst];k++
){
long long num=
f[lst][k];
int zt=a[lst][k],b1=(zt>>((j-
1)*
2))%
4,b2=(zt>>(j*
2))%
4;
if(mp[i][j]==
'#'){
if(!b1&&!
b2)ins(zt,num);
}
else if(!b1&&!
b2){
if(mp[i][j]==
'.'&&(mp[i+
1][j]==
'|'||mp[i+
1][j]==
'.')&&(mp[i][j+
1]==
'-'||mp[i][j+
1]==
'.')){
ins(zt+sit[j-
1]+sit[j]*
2,num);
}
}
else if(b1&&!
b2){
if((mp[i+
1][j]==
'.'||mp[i+
1][j]==
'|')&&mp[i][j]!=
'-'&&mp[i][j]!=
'|')ins(zt,num);
if((mp[i][j+
1]==
'.'||mp[i][j+
1]==
'-')&&mp[i][j]!=
'|')ins(zt-sit[j-
1]*b1+sit[j]*
b1,num);
}
else if(!b1&&
b2){
if((mp[i][j+
1]==
'.'||mp[i][j+
1]==
'-')&&mp[i][j]!=
'-'&&mp[i][j]!=
'|')ins(zt,num);
if((mp[i+
1][j]==
'.'||mp[i+
1][j]==
'|')&&mp[i][j]!=
'-')ins(zt-sit[j]*b2+sit[j-
1]*
b2,num);
}
else if(b1==
1&&b2==
1){
if(mp[i][j]!=
'-'&&mp[i][j]!=
'|'){
int kl=
1;
for(
int t=j+
1;t<=m;t++
){
if((zt>>(t*
2))%
4==
1)kl++
;
if((zt>>(t*
2))%
4==
2)kl--
;
if(!
kl){
ins(zt-sit[j]-sit[j-
1]-
sit[t],num);
break;
}
}
}
}
else if(b1==
2&&b2==
2){
if(mp[i][j]!=
'-'&&mp[i][j]!=
'|'){
int kl=
1;
for(
int t=j-
2;t>
0;t--
){
if((zt>>(t*
2))%
4==
1)kl--
;
if((zt>>(t*
2))%
4==
2)kl++
;
if(!
kl){
ins(zt-sit[j]*
2-sit[j-
1]*
2+
sit[t],num);
break;
}
}
}
}
else if(b1==
2&&b2==
1){
if(mp[i][j]!=
'-'&&mp[i][j]!=
'|'){
ins(zt-sit[j-
1]*
2-
sit[j],num);
}
}
else if(i==e1&&j==e2&&mp[i][j]!=
'-'&&mp[i][j]!=
'|'){
//伏笔还是要收的,久等了【大雾】
// 上一道题没有用到e1e2,第二道题我又是照着标程改的,然后完美忘记,从(n,m)的地方累计答案去了
//居然还有90分,折腾了半天细节,结果是这里…
ans+=
num;
}
}
}
}
}
int main()
{
scanf("%d%d",&n,&
m);
for(
int i=
1;i<=n;i++
){
scanf("%s",s+
1);
for(
int j=
1;j<=m;j++
){
mp[i][j]=
s[j];
if(j==
1||j==
m){
if(mp[i][j]==
'-'){
printf("0");
return 0;
}
}
if(i==
1||i==
n){
if(mp[i][j]==
'|'){
printf("0");
return 0;
}
}
if(mp[i][j]!=
'#')e1=i,e2=j;
//伏 笔 回 收 ,欠下的总是要还的
}
}
sit[0]=
1;
for(
int i=
1;i<=
13;i++)sit[i]=sit[i-
1]<<
2;
work();
printf("%lld",ans);
return 0;
}
今天也在非常认真地怀疑自己的智商
转载于:https://www.cnblogs.com/chloris/p/11260955.html
相关资源:JAVA上百实例源码以及开源项目