事先声明,对题目并无恶意中伤,题目承受的痛苦由傻逼本人(我)来承担。
55/50/45/0
简单的广搜,居然没注意有很多洪水,反正各开一个队列,先洪水再人即可。
1 #include<bits/stdc++.h> 2 #pragma GCC optimize(3) 3 using namespace std; 4 #define f(i,a,b) for(int i=a;i<=b;i++) 5 const int N=60; 6 const int T=120; 7 int r,c; 8 struct pos{ 9 int x,y,t; 10 }D,S,F; 11 int ma[N][N],t,x[5]={1,0,-1,0},y[5]={0,1,0,-1},vis[N][N]; 12 queue<pos> p; 13 queue<pos> q; 14 char a; 15 void out(pos a){ 16 cout<<"pos:"<<a.x<<" "<<a.y<<endl; 17 for(int i=1;i<=r;i++){ 18 for(int j=1;j<=c;j++){ 19 cout<<ma[i][j]<<" "; 20 } 21 cout<<endl; 22 } 23 } 24 int main(){ 25 while(!p.empty()) p.pop(); 26 while(!q.empty()) q.pop(); 27 // freopen("data1.in","r",stdin); 28 scanf("%d%d",&r,&c); 29 f(i,1,r){ 30 f(j,1,c){ 31 scanf("%1s",&a); 32 if(a=='D'){ 33 D.x=i,D.y=j; 34 ma[i][j]=2; 35 } 36 else if(a=='S'){ 37 S.x=i,S.y=j,S.t=1; 38 ma[i][j]=1; 39 } 40 else if(a=='*'){ 41 p.push((pos){i,j,1}); 42 ma[i][j]=3; 43 } 44 else if(a=='X'){ 45 ma[i][j]=4; 46 } 47 else; 48 } 49 } 50 q.push(S); 51 while(1){ 52 t++; 53 pos nowf=p.front(); 54 while(nowf.t==t){ 55 p.pop(); 56 f(i,0,3){ 57 if(nowf.x+x[i]<=0||nowf.x+x[i]>r||nowf.y+y[i]<=0||nowf.y+y[i]>c) continue; 58 if(!ma[nowf.x+x[i]][nowf.y+y[i]]){ 59 ma[nowf.x+x[i]][nowf.y+y[i]]=3; 60 p.push((pos){nowf.x+x[i],nowf.y+y[i],t+1}); 61 } 62 } 63 nowf=p.front(); 64 } 65 bool flag=0; 66 pos nowd=q.front(); 67 while(nowd.t==t){ 68 // out(nowd); 69 q.pop(); 70 f(i,0,3){ 71 if(nowd.x+x[i]<=0||nowd.x+x[i]>r||nowd.y+y[i]<=0||nowd.y+y[i]>c) continue; 72 if(vis[nowd.x+x[i]][nowd.y+y[i]]) continue; 73 if(!ma[nowd.x+x[i]][nowd.y+y[i]]){ 74 vis[nowd.x+x[i]][nowd.y+y[i]]=1; 75 q.push((pos){nowd.x+x[i],nowd.y+y[i],t+1}); 76 flag=1; 77 } 78 else if(ma[nowd.x+x[i]][nowd.y+y[i]]==2){ 79 printf("%d",t); 80 return 0; 81 } 82 } 83 nowd=q.front(); 84 } 85 if(!flag){ 86 printf("KAKTUS\n"); 87 return 0; 88 } 89 } 90 return 0; 91 }
1236. 邦德I (Standard IO)
Time Limits: 2000 ms Memory Limits: 65536 KB Detailed Limits
Goto ProblemSet第一眼看这题,误以为数据是50,就没想到正解(但听说打搜索剪枝有95分),明显是状压DP,设f[i][j]表示第i行状态为j的最大概率(j中有1个1),设s[i][j]表示第i行状态为j的最大概率(j中有i个1),枚举上一行的s[i][j],找出不冲突的状态转移取最大值即可。
后注:
1.你妈的,调了俩小时发现数组开小了。
2.听说这题还能用二分图做,二分图最大匹配的时候,利用对数性质把乘积变成对数的和即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=21; 4 int n; 5 double sum[2][1<<N]; 6 int num[1<<N]; 7 int mis[N][N],q; 8 void ini(){ 9 for(int i=1;i<(1<<n);i++){ 10 int t=i; 11 int ans=0; 12 while(t){ 13 if(t&1) ans++; 14 t>>=1; 15 } 16 num[i]=ans; 17 } 18 for(int i=1,k=1;i<(1<<n);i<<=1,k++){ 19 sum[1][i]=mis[1][k]; 20 } 21 } 22 int main(){ 23 memset(sum,0,sizeof(sum)); 24 memset(mis,0,sizeof(mis)); 25 memset(num,0,sizeof(num));//毫无卵用 26 // freopen("data.in","r",stdin); 27 scanf("%d",&n); 28 for(int i=1;i<=n;i++){ 29 for(int j=1;j<=n;j++){ 30 scanf("%d",&mis[i][j]); 31 } 32 } 33 ini(); 34 for(int i=2;i<=n;i++){ 35 q=i%2; 36 for(int k=1,l=1;k<(1<<n);k<<=1,l++){ 37 for(int j=1;j<(1<<n);j++){ 38 if(num[j]!=i-1||j&k) continue; 39 sum[q][j|k]=max(sum[q][j|k],sum[q^1][j]*mis[i][l]/100); 40 // cout<<sum[q][j|k]<<endl; 41 } 42 } 43 } 44 printf("%.6f",sum[q][(1<<n)-1]); 45 return 0; 46 }
想到动态规划,但考试的时候列错了。
正解:设h[i][j]表示点(i,j)向上方扩展的最高位置,l[i][j],r[i][j]分别表示在最高位置向左或者向右能到达的最远位置,用前缀和预处理一下即可。
不知道为啥内存会炸,明明没超过的。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2100; 4 int r,c; 5 int a[N][N],ans; 6 int sum[N][N],h[N][N],ll[N][N],rr[N][N]; 7 char t; 8 int getsum(int x1,int y1,int x2,int y2){ 9 return sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]; 10 } 11 int main(){ 12 scanf("%d%d",&r,&c); 13 for(int i=1;i<=r;i++){ 14 for(int j=1;j<=c;j++){ 15 scanf("%1s",&t); 16 a[i][j]=(t=='.'?1:0); 17 sum[i][j]=sum[i-1][j]+sum[i][j-1]+a[i][j]-sum[i-1][j-1]; 18 } 19 } 20 21 for(int i=1;i<=r;i++){ 22 for(int j=1;j<=c;j++){ 23 if(!a[i][j]) continue; 24 for(int l=1;i+l<=r;l++){ 25 if(a[i+l][j]) h[i][j]=l; 26 else break; 27 } 28 } 29 } 30 31 for(int i=1;i<=r;i++){ 32 for(int j=1;j<=c;j++){ 33 if(!a[i][j]) continue; 34 for(int l=1;j+l<=c;l++){ 35 if(getsum(i,j,i+h[i][j],j+l)==(h[i][j]+1)*(l+1)) rr[i][j]=l; 36 else break; 37 } 38 } 39 } 40 41 for(int i=1;i<=r;i++){ 42 for(int j=1;j<=c;j++){ 43 if(!a[i][j]) continue; 44 for(int l=1;j-l>0;l++){ 45 if(getsum(i,j-l,h[i][j]+i,j)==(h[i][j]+1)*(l+1)) ll[i][j]=l; 46 else break; 47 } 48 } 49 } 50 for(int i=1;i<=r;i++){ 51 for(int j=1;j<=c;j++){ 52 ans=max(ans,(h[i][j]+1+rr[i][j]+ll[i][j]+1)*2); 53 } 54 } 55 printf("%d",ans-1); 56 return 0; 57 }
1238. 自行车比赛 (Standard IO)
Time Limits: 1000 ms Memory Limits: 65536 KB Detailed Limits
Goto ProblemSet拓扑排序判环+dp计算答案,标程不写了。
总结:加油上300分就滚去A组玩啊!要不250也行,总之至少A过俩题吧!