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过俩题吧!

    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    88. Merge Sorted Array
    87. Scramble String
    86. Partition List
    85. Maximal Rectangle
    84. Largest Rectangle in Histogram
    83. Remove Duplicates from Sorted List
    82. Remove Duplicates from Sorted List II
    81. Search in Rotated Sorted Array II
    80. Remove Duplicates from Sorted Array II
    计算几何——点线关系(叉积)poj2318
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11332657.html
Copyright © 2011-2022 走看看