zoukankan      html  css  js  c++  java
  • SHU 2013 暑期集训(7-17)解题报告

    Problem A  (hdu 1261)

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 71   Accepted Submission(s) : 14

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    一个A和两个B一共可以组成三种字符串:"ABB","BAB","BBA".
    给定若干字母和它们相应的个数,计算一共可以组成多少个不同的字符串.

    Input

    每组测试数据分两行,第一行为n(1<=n<=26),表示不同字母的个数,第二行为n个数A1,A2,...,An(1<=Ai<=12),表示每种字母的个数.测试数据以n=0为结束.

    Output

    对于每一组测试数据,输出一个m,表示一共有多少种字符串.

    Sample Input

    2
    1 2
    3
    2 2 2
    0
    

    Sample Output

    3
    90
    题目大意:给你n个字符,每个字符有a[i]个,问有多少种排列。
    分析:公式比较容易推,就是sum!/(a[1]!*a[2]!*...*a[n]!),但需要高精度,本来写了高精度sum!除以高精度(a[1]!*a[2]!*...*a[n]!),但可恶的wa了,估计是写烂了。后来听了小贤的讲解,想到了另一种写法,就是先使用高精度算sum!,在计算sum!除以a[i]!的时候,枚举a[i]的每一个元素(2-a[i]),除以这个数(高精度)。
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 int ans[1000],len;
     6 int n,num[50],sum;
     7 void f(int n)
     8 {
     9     int carry,temp;
    10     ans[0]=1;len=1;
    11     for(int i=2;i<=n;++i)
    12     {
    13         carry=0;
    14         for(int j=0;j<len;++j)
    15         {
    16             temp=ans[j]*i+carry;
    17             ans[j]=temp%10000;
    18             carry=temp/10000;
    19         }
    20         if(carry)
    21             ans[len++]=carry;
    22     }
    23 }
    24 int main()
    25 {
    26     while(scanf("%d",&n)!=EOF&&n)
    27     {
    28        sum=0;
    29        for(int i=0;i<n;++i)
    30        {
    31            scanf("%d",&num[i]);
    32            sum+=num[i];
    33        }
    34        f(sum);
    35        for(int i=0;i<n;++i)
    36        {
    37            for(int j=2;j<=num[i];++j)//枚举因子
    38            {
    39                int carry=0;
    40                for(int k=len-1;k>=0;--k)
    41                {
    42                    int temp=ans[k]+carry*10000;
    43                    ans[k]=temp/j;
    44                    carry=temp%j;
    45                }
    46                while(ans[len-1]==0)
    47                    len--;
    48            }
    49        }
    50        printf("%d",ans[len-1]);
    51        for(int i=len-2;i>=0;--i)
    52            printf("%04d",ans[i]);
    53        printf("
    ");
    54     }
    55 }
    View Code

    Problem B(hdu 1312)

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 27   Accepted Submission(s) : 19

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.

    Write a program to count the number of black tiles which he can reach by repeating the moves described above. 

    Input

    The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in the x- and y- directions, respectively. W and H are not more than 20.

    There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

    '.' - a black tile 
    '#' - a red tile 
    '@' - a man on a black tile(appears exactly once in a data set) 

    Output

    For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself). 

    Sample Input

    6 9
    ....#.
    .....#
    ......
    ......
    ......
    ......
    ......
    #@...#
    .#..#.
    11 9
    .#.........
    .#.#######.
    .#.#.....#.
    .#.#.###.#.
    .#.#..@#.#.
    .#.#####.#.
    .#.......#.
    .#########.
    ...........
    11 6
    ..#..#..#..
    ..#..#..#..
    ..#..#..###
    ..#..#..#@.
    ..#..#..#..
    ..#..#..#..
    7 7
    ..#.#..
    ..#.#..
    ###.###
    ...@...
    ###.###
    ..#.#..
    ..#.#..
    0 0
    

    Sample Output

    45
    59
    6
    13
    

     题目大意:给你一个地图,'@'为你的起始点,'.'为可以走的点,'#'为墙,问你最多可以走过多少个'.'(包括'@')。

    分析:简单搜索,现在到自己的位置,'@'的位置,从这一点向四个方向搜索,遇到'.'可以走,继续递归下去并标记为'#'与计数。

    最后输出数值即可。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxlen 1100
     5 using namespace std;
     6 char maps[maxlen][maxlen];
     7 int n,m;
     8 int xx[]= {-1, 0, 0, 1};
     9 int yy[]= { 0,-1, 1, 0};
    10 int sx,sy,cnt;
    11 void init()
    12 {
    13     for(int i=1; i<=n; ++i)
    14         for(int  j=1; j<=m; ++j)
    15             maps[i][j]='#';
    16     for(int i=1; i<=n; ++i)
    17     {
    18         for(int j=1; j<=m; ++j)
    19         {
    20             cin>>maps[i][j];
    21             if(maps[i][j]=='@')
    22             {
    23                 sx=i;
    24                 sy=j;
    25             }
    26         }
    27     }
    28 }
    29 bool judge(int x,int y)
    30 {
    31     return x>=1&&x<=n&&y>=1&&y<=m&&maps[x][y]=='.';
    32 }
    33 void dfs(int x,int y)
    34 {
    35     cnt++;
    36     for(int i=0; i<4; ++i)
    37     {
    38         int tx=x+xx[i];
    39         int ty=y+yy[i];
    40         if(judge(tx,ty))
    41         {
    42             maps[tx][ty]='#';
    43             dfs(tx,ty);
    44         }
    45     }
    46 }
    47 int main ()
    48 {
    49     while(scanf("%d%d",&m,&n)!=EOF)
    50     {
    51         getchar();
    52         if(n==0&&m==0)
    53             break;
    54         init();
    55         cnt=0;
    56         maps[sx][sy]='#';
    57         dfs(sx,sy);
    58         printf("%d
    ",cnt);
    59     }
    60 }
    View Code

    Problem D(hdu 1195)

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 16   Accepted Submission(s) : 7

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    Now an emergent task for you is to open a password lock. The password is consisted of four digits. Each digit is numbered from 1 to 9. 
    Each time, you can add or minus 1 to any digit. When add 1 to '9', the digit will change to be '1' and when minus 1 to '1', the digit will change to be '9'. You can also exchange the digit with its neighbor. Each action will take one step.

    Now your task is to use minimal steps to open the lock.

    Note: The leftmost digit is not the neighbor of the rightmost digit.

    Input

    The input file begins with an integer T, indicating the number of test cases. 

    Each test case begins with a four digit N, indicating the initial state of the password lock. Then followed a line with anotther four dight M, indicating the password which can open the lock. There is one blank line after each test case.

    Output

    For each test case, print the minimal steps in one line.

    Sample Input

    2
    1234
    2144
    
    1111
    9999
    

    Sample Output

    2
    4
    题目大意:给你4位的密码以及一个4位的数字,你可以将某一位的数字+1或-1或将其与相邻的数字交换。问最少多少次操作将其变为得到密码。
    分析:搜索,4位数一共有13种变换方式,+1(4种),-1(4种),交换(3种),枚举每一种变换去一个最小值即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 using namespace std;
      6 int visited[11][11][11][11];
      7 struct node
      8 {
      9     int num[6];
     10     int step;
     11 } snum,endnum;
     12 void init()
     13 {
     14     int s,e;
     15     scanf("%d%d",&s,&e);
     16     for(int i=4; i>=1; --i)
     17     {
     18         snum.num[i]=s%10;
     19         s/=10;
     20     }
     21     for(int i=4; i>=1; --i)
     22     {
     23         endnum.num[i]=e%10;
     24         e/=10;
     25     }
     26 }
     27 void bfs()
     28 {
     29     node nows,nexts;
     30     queue<node>q;
     31     nows=snum;
     32     nows.step=0;
     33     q.push(nows);
     34     memset(visited,0,sizeof(visited));
     35     visited[nows.num[0]][nows.num[1]][nows.num[2]][nows.num[3]]=1;
     36     while(!q.empty())
     37     {
     38         nows=q.front();
     39         q.pop();
     40         int flag=1;
     41         for(int i=1; i<=4; i++)
     42         {
     43             if(nows.num[i]!=endnum.num[i])
     44             {
     45                 flag=0;
     46                 break;
     47             }
     48         }
     49         if(flag)
     50         {
     51             printf("%d
    ",nows.step);
     52             return;
     53         }
     54         for(int i=1; i<=4; i++)//+1
     55         {
     56             nexts=nows;
     57             if(nows.num[i]>=1&&nows.num[i]<=8)
     58                 nexts.num[i]+=1;
     59             else
     60                 nexts.num[i]=1;
     61             if(!visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]])
     62             {
     63                 visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]]=1;
     64                 nexts.step=nows.step+1;
     65                 q.push(nexts);
     66             }
     67         }
     68         for(int i=1; i<=4; i++)//-1
     69         {
     70             nexts=nows;
     71             if(nows.num[i]>=2&&nows.num[i]<=9)
     72                 nexts.num[i]-=1;
     73             else
     74                 nexts.num[i]=9;
     75             if(!visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]])
     76             {
     77                 visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]]=1;
     78                 nexts.step=nows.step+1;
     79                 q.push(nexts);
     80             }
     81         }
     82         for(int i=1; i<=3; i++)//swap
     83         {
     84             nexts=nows;
     85             nexts.num[i]=nows.num[i+1];
     86             nexts.num[i+1]=nows.num[i];
     87             if(!visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]])
     88             {
     89                 visited[nexts.num[1]][nexts.num[2]][nexts.num[3]][nexts.num[4]]=1;
     90                 nexts.step=nows.step+1;
     91                 q.push(nexts);
     92             }
     93         }
     94     }
     95     return;
     96 }
     97 int main()
     98 {
     99     int t;
    100     scanf("%d",&t);
    101     while(t--)
    102     {
    103         init();
    104         bfs();
    105     }
    106 }
    View Code

    Problem G (hdu 2191)

    Time Limit : 1000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
    Total Submission(s) : 24   Accepted Submission(s) : 15

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    急!灾区的食物依然短缺!
    为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋购买。
    请问:你用有限的资金最多能采购多少公斤粮食呢?

    后记:
    人生是一个充满了变数的生命过程,天灾、人祸、病痛是我们生命历程中不可预知的威胁。
    月有阴晴圆缺,人有旦夕祸福,未来对于我们而言是一个未知数。那么,我们要做的就应该是珍惜现在,感恩生活——
    感谢父母,他们给予我们生命,抚养我们成人;
    感谢老师,他们授给我们知识,教我们做人
    感谢朋友,他们让我们感受到世界的温暖;
    感谢对手,他们令我们不断进取、努力。 
    同样,我们也要感谢痛苦与艰辛带给我们的财富~

    Input

    输入数据首先包含一个正整数C,表示有C组测试用例,每组测试用例的第一行是两个整数n和m(1<=n<=100, 1<=m<=100),分别表示经费的金额和大米的种类,然后是m行数据,每行包含3个数p,h和c(1<=p<=20,1<=h<=200,1<=c<=20),分别表示每袋的价格、每袋的重量以及对应种类大米的袋数。

    Output

    对于每组测试数据,请输出能够购买大米的最多重量,你可以假设经费买不光所有的大米,并且经费你可以不用完。每个实例的输出占一行。

    Sample Input

    1
    8 2
    2 100 4
    4 100 2
    

    Sample Output

    400
    题目大意:n容量的资金,m种物品,每种物品价格为p[i],重量w[i],数量num[i],问获得最大的重量为多少。
    分析:多重背包模板题,这题的m比较小,可以将其全都拆成0-1背包求解,如果碰到m较大的情况,可以使用2进制优化的方式,即将num[i]拆成2的指数形式(1,2,4,8)在进行选择。
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxlen 1010
     5 using namespace std;
     6 int dp[maxlen],W;
     7 int p[maxlen],w[maxlen],num[maxlen];
     8 void ZeroOnePack(int cost,int weight)
     9 {
    10     for(int i=W; i>=weight; i--)
    11         dp[i]=max(dp[i],dp[i-weight]+cost);
    12 }
    13 void ComletePack(int cost,int weight)
    14 {
    15     for(int i=weight; i<=W; i++)
    16         dp[i]=max(dp[i],dp[i-weight]+cost);
    17 }
    18 void MultiPack(int cost ,int weight,int num)
    19 {
    20     if(num*weight>=W)
    21         ComletePack(cost,weight);
    22     else
    23     {
    24         int k=1;
    25         while(k<num)
    26         {
    27             ZeroOnePack(cost*k,weight*k);
    28             num-=k;
    29             k*=2;
    30         }
    31         ZeroOnePack(cost*num,weight*num);
    32     }
    33 }
    34 int main()
    35 {
    36     int t,n;
    37     scanf("%d",&t);
    38     while(t--)
    39     {
    40         scanf("%d%d",&W,&n);
    41         for(int i=0; i<n; i++)
    42             scanf("%d%d%d",&p[i],&w[i],&num[i]);
    43         memset(dp,0,sizeof(dp));
    44         for(int i=0; i<n; i++)
    45             MultiPack(w[i],p[i],num[i]);
    46         printf("%d
    ",dp[W]);
    47     }
    48     return 0;
    49 }
    View Code

    Problem I (hdu 2032)

    Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
    Total Submission(s) : 72   Accepted Submission(s) : 22

    Font: Times New Roman | Verdana | Georgia

    Font Size:  

    Problem Description

    还记得中学时候学过的杨辉三角吗?具体的定义这里不再描述,你可以参考以下的图形:
    1
    1 1
    1 2 1
    1 3 3 1
    1 4 6 4 1
    1 5 10 10 5 1

    Input

    输入数据包含多个测试实例,每个测试实例的输入只包含一个正整数n(1<=n<=30),表示将要输出的杨辉三角的层数。

    Output

    对应于每一个输入,请输出相应层数的杨辉三角,每一层的整数之间用一个空格隔开,每一个杨辉三角后面加一个空行。

    Sample Input

    2 3
    

    Sample Output

    1
    1 1
    
    1
    1 1
    1 2 1
    题目大意:打印杨辉三角。
    分析:水题,直接递推然后输出即可。
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define maxlen 110
     5 using namespace std;
     6 int maps[maxlen][maxlen];
     7 int n;
     8 void DisPlay(int s)
     9 {
    10     for(int i=1;i<=s;++i)
    11     {
    12         for(int j=1;j<=i;++j)
    13         {
    14             if(j!=i)
    15             cout<<maps[i][j]<<" ";
    16             else
    17                 cout<<maps[i][j];
    18         }
    19         cout<<endl;
    20     }
    21 }
    22 int main ()
    23 {
    24     memset(maps,0,sizeof(maps));
    25     maps[1][1]=1;
    26     for(int i=2;i<=30;++i)
    27     {
    28         for(int j=1;j<=30;++j)
    29         {
    30             maps[i][j]=maps[i-1][j]+maps[i-1][j-1];
    31         }
    32     }
    33     while(scanf("%d",&n)!=EOF)
    34     {
    35         DisPlay(n);
    36         cout<<endl;
    37     }
    38 }
    View Code

    总结:还是太弱,两道数学题完全不会,搜索写的还不是很熟练,没做的题尽量填坑。

  • 相关阅读:
    CentOS 6 安装 python and pip
    Qt for Windows:Qt 5.4.0 MinGW 静态编译版本制作 (转)
    Vim 扩展工具 vim-ide (转)
    centos yum 完全卸载依赖
    Linux修改Shell命令提示符及颜色
    tmux 命令
    网络分析shell脚本(实时流量+连接统计)
    ICMP:Internet控制报文协议
    读《分布式一致性原理》zookeeper运维
    同网段和不同网段设备通信原理详解
  • 原文地址:https://www.cnblogs.com/shuzy/p/3199583.html
Copyright © 2011-2022 走看看