事先声明,对题目并无恶意中伤,题目承受的痛苦由傻逼本人(我)来承担。
55/50/45/0
Description
一天, 一个画家在森林里写生,突然爆发了山洪,他需要尽快返回住所中,那里是安
全的。
森林的地图由R行C列组成,空白区域用点“.”表示,洪水的区域用“*”表示,而
岩石用“X”表示,另画家的住所用“D”表示,画家用“S”表示。
有以下几点需要说明:
1、 每一分钟画家能向四个方向移动一格(上、下、左、右)
2、 每一分钟洪水能蔓延到四个方向的相邻格子(空白区域)
3、 洪水和画家都不能通过岩石区域
4、 画家不能通过洪水区域(同时也不行,即画家不能移到某个格子,该格子在画家达到的同时被洪水蔓延到了,这也是不允许的)
5、 洪水蔓不到画家的住所。
给你森林的地图,编写程序输出最少需要花费多长时间才能从开始的位置赶回家中。
Input
输入第一行包含两个整数R和C(R,C<=50)。
接下来R行每行包含C个字符(“.”、“*”、“X”、“D”或“S”)。地图保证只有一个“D”和一个“S”。
接下来R行每行包含C个字符(“.”、“*”、“X”、“D”或“S”)。地图保证只有一个“D”和一个“S”。
Output
输出画家最快安全到达住所所需的时间,如果画家不可能安全回家则输出“KAKTUS”。
Sample Input
输入1: 3 3 D.* ... .S. 输入2: 3 3 D.* ... ..S 输入3: 3 6 D...*. .X.X.. ....S.
Sample Output
输出1: 3 输出2: KAKTUS 输出3: 6
简单的广搜,居然没注意有很多洪水,反正各开一个队列,先洪水再人即可。
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
Description
每个人都知道詹姆斯邦德,著名的007,但很少有人知道很多任务都不是他亲自完成的,而是由他的堂弟们吉米邦德完成(他有很多堂弟),詹姆斯已经厌倦了把一个个任务分配给一个个吉米,他向你求助。
每个月,詹姆斯都会收到一些任务,根据他以前执行任务的经验,他计算出了每个吉米完成每个任务的成功率,要求每个任务必须分配给不同的人去完成,每个人只能完成一个任务。
请你编写程序找到一个分配方案使得所有任务都成功完成的概率。
每个月,詹姆斯都会收到一些任务,根据他以前执行任务的经验,他计算出了每个吉米完成每个任务的成功率,要求每个任务必须分配给不同的人去完成,每个人只能完成一个任务。
请你编写程序找到一个分配方案使得所有任务都成功完成的概率。
Input
输入第一行包含一个整数N,表示吉米邦德的数量以及任务的数量(正好相等,1<=N<=20)。
接下来N行,每行包含N个0到100之间整数,第i行的第j个数Aij表示吉米邦德i完成任务j成功的概率为Aij%
接下来N行,每行包含N个0到100之间整数,第i行的第j个数Aij表示吉米邦德i完成任务j成功的概率为Aij%
Output
输出所有任务成功完成最大的概率,结果保留6位小数。
Sample Input
输入1: 2 100 100 50 50 输入2: 2 0 50 50 0 输入3: 3 25 60 100 13 0 50 12 70 90
Sample Output
输出1: 50.000000 输出2: 25.000000 输出3: 9.100000
第一眼看这题,误以为数据是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 }
Description
你家刚买了一套新房,想邀请朋友回来庆祝,所以需要一个很大的举行餐桌,餐桌能容纳的人数等于餐桌的周长,你想买一个能容纳最多人的餐桌,餐桌的边必须跟房间的边平行。
给你的房间的设计,计算最多能邀请的客人数。
给你的房间的设计,计算最多能邀请的客人数。
Input
第一行包含两个整数R和C(1<=R,C<=2000),表示房子的长和宽。
接下来R行每行S个字符(中间没有空格),“.”表示空白区域,“X”表示有障碍物,餐桌所占区域必须是空白的。
接下来R行每行S个字符(中间没有空格),“.”表示空白区域,“X”表示有障碍物,餐桌所占区域必须是空白的。
Output
输出最多能要求的客人数量。
Sample Input
输入1: 2 2 .. .. 输入2: 4 4 X.XX X..X ..X. ..XX 输入3: 3 3 X.X .X. X.X
Sample Output
输出1: 7 输出2: 9 输出3: 3
Data Constraint
Hint
【数据规模】
50%的数据R,C<=400
70%的数据R,C<=1000
100%的数据,R,C<=2000
50%的数据R,C<=400
70%的数据R,C<=1000
100%的数据,R,C<=2000
想到动态规划,但考试的时候列错了。
正解:设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
Description
自行车赛在一个很大的地方举行,有N个镇,用1到N编号,镇与镇之间有M条单行道相连,起点设在镇1,终点设在镇2。
问从起点到终点一共有多少种不同的路线。两条路线只要不使用完全相同的道路就被认为是不同的。
问从起点到终点一共有多少种不同的路线。两条路线只要不使用完全相同的道路就被认为是不同的。
Input
第一行两个整数:N和M(1<=N<=10000,1<=M<=100000),表示镇的数量和道路的数量。
接下来M行,每行包含两个不同的整数A和B,表示有一条从镇A到镇B的单行道。
两个镇之间有可能不止一条路连接。
接下来M行,每行包含两个不同的整数A和B,表示有一条从镇A到镇B的单行道。
两个镇之间有可能不止一条路连接。
Output
输出不同路线的数量,如果答案超过9位,只需输出最后9位数字。如果有无穷多的路线,输出“inf”。
Sample Input
输入1: 6 7 1 3 1 4 3 2 4 2 5 6 6 5 3 4 输入2: 6 8 1 3 1 4 3 2 4 2 5 6 6 5 3 4 4 3 输入3: 31 60 1 3 1 3 3 4 3 4 4 5 4 5 5 6 5 6 6 7 6 7 … … … 28 29 28 29 29 30 29 30 30 31 30 31 31 2 31 2
Sample Output
输出1: 3 输出2: inf 输出3: 073741824
拓扑排序判环+dp计算答案,标程不写了。
总结:加油上300分就滚去A组玩啊!要不250也行,总之至少A过俩题吧!