zoukankan      html  css  js  c++  java
  • 【纪中受难记】——Day11:傻逼题遇上傻逼人

    事先声明,对题目并无恶意中伤,题目承受的痛苦由傻逼本人(我)来承担。

    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”。

    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 }

    Description

    每个人都知道詹姆斯邦德,著名的007,但很少有人知道很多任务都不是他亲自完成的,而是由他的堂弟们吉米邦德完成(他有很多堂弟),詹姆斯已经厌倦了把一个个任务分配给一个个吉米,他向你求助。
    每个月,詹姆斯都会收到一些任务,根据他以前执行任务的经验,他计算出了每个吉米完成每个任务的成功率,要求每个任务必须分配给不同的人去完成,每个人只能完成一个任务。
    请你编写程序找到一个分配方案使得所有任务都成功完成的概率。
     

    Input

    输入第一行包含一个整数N,表示吉米邦德的数量以及任务的数量(正好相等,1<=N<=20)。
    接下来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”表示有障碍物,餐桌所占区域必须是空白的。

    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

    想到动态规划,但考试的时候列错了。

    正解:设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 }

    Description

    自行车赛在一个很大的地方举行,有N个镇,用1到N编号,镇与镇之间有M条单行道相连,起点设在镇1,终点设在镇2。
    问从起点到终点一共有多少种不同的路线。两条路线只要不使用完全相同的道路就被认为是不同的。
     

    Input

    第一行两个整数:N和M(1<=N<=10000,1<=M<=100000),表示镇的数量和道路的数量。
    接下来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过俩题吧!

    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    爬虫笔记之JS检测浏览器开发者工具是否打开
    上海租房@8群
    在Windows中玩转Docker Toolbox(镜像加速)
    Docker 清理命令 删除所有的镜像和容器
    修改docker安装的machine位置
    Sass @mixin 与 @include
    webpack之SourceMap
    c#中Indexof()和Split()的用法
    《MVC+EF》——用DBFirst创建ADO.NET实体数据模型和对象关系映射
    sql server 用户'sa'登录失败(错误18456)
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11332657.html
Copyright © 2011-2022 走看看