【洛谷月赛】洛谷11月月赛·Day1

洛谷2614 计算器弹琴

本题地址: http://www.luogu.org/problem/show?pid=2614

题目描述

总所周知,计算器可以拿来干很多它本不应该干的事情,比如写作文。(参看洛谷P2549)
小A发现了一个计算器的另一个隐藏功能——弹琴。
http://www.bilibili.com/video/av2205500/

如果按上一个键,比如说1,就会发出中音“Do”。
这边给出按键音高表
+ 低音Fa
< 低音So
* 低音La
/ 低音Xi
1 中音Do
2 中音Re
3 中音Mi
4 中音Fa
5 中音So
6 中音La
7 高音Xi
8 高音Do
9 高音Re
= 高音Mi
% 高音Fa
C 高音So
M 高音La

现在小A搞到了一份乐谱——我们称为计算器谱,一种变形的简谱。
时值(也就是按的时间长度)是这么记录的,例如:
1 是四分音符,占1拍。
1- 是二分音符,占2拍。
1— 是全音符,占四拍。
对于小于四分音符的音符,我们用嵌套括号表示,例如
(1(34(56))2)
1和2在一层括号中,是八分音符,占0.5拍。
3和4在两层括号中,是16分音符,占0.25拍。
5和6在三层括号中,是32分音符,占1/8拍。当然实际上比较少见。
括号中不会出现‘-’这个符号。
不会出现四层或以上的括号。
在一个音符后面添加一个附点即“.”表示这个音符延长1/2倍。
例如
1-.是3拍,1.是1.5拍,(3.(45.))3是3/4拍,4是1/4拍,5是3/8拍。
附点不会连续添加两个或以上,也不会出现超过四拍的音符。
不考虑其他的乐理符号。
另外整个乐谱会给一个速度,整数,意思是一分钟多少拍。

为了美观,乐谱可以随便换行、添加空格。这个忽略即可。
现在小A想知道,按完这个谱子,需要多少时间(单位:秒)

输入输出格式

输入格式:

第一行,两个整数n,T,表示谱子行数以及速度(拍每分)
接下来n行,给出乐谱。

输出格式:

一个整数,表示演奏需要花费的时间,单位秒,舍去小数部分。

输入输出样例

输入样例#1:

2 60
3345 5432 1123 322-
3345 5432 1123 211-

输出样例#1:

32
(一共32拍,每分钟60拍,所以是32秒。对了,这是欢乐颂的开头部分)

输入样例#2:

5 120
3(1.(3))55 8(7.(6))65 655(3.(1)) (4.(4))32- 
3(1.(2))35 8(7.(6))65 655(4.(3)) (2.(3))21- 
2.(3)44 6(6.(6))(5.(4))3 3.(5)88 (9.(8)7.(6))5-
=.(=)(9.(8))7 9.(8)(7.(6))5  8(856543) (2.(3))43- 
=.(=)(9.(8))7 9.(8)(7.(6))5  8(857654) (3.(4))21- 

输出样例#2:

40
(一共80拍,别问我怎么数的,一分钟120拍的话,是40秒。至于这是什么曲子?根据相关的法律政策,该部分未予显示。)

说明

http://bd.kuwo.cn/yinyue/4641527

对于40%的数据,没有附点没有括号
对于100%的数据,括号层数不会超过3层,不超过100行,每行不超过100个字符。
对于其中的一个数据,是《千本樱》。


括号匹配。用栈来维护。

其实蛮喜欢题目中有千本樱和B站的2333

代码:

#include
#include
#include
#include
#include
using namespace std;

stack<double> s;
int main()
{
    int n;
    double m;
    scanf("%d%lf",&n,&m);
    string in;
    double g=1.0;
    while(cin>>in)
    {
        for(int i=0;i<(int)in.length();i++)
        {
            if(in[i]!='-'&&in[i]!='.'&&in[i]!='('&&in[i]!=')')
            {
                s.push(1.0*g);
            }
            if(in[i]=='-') s.top()++;
            if(in[i]=='(') g/=2.0;
            if(in[i]==')') g*=2.0;
            if(in[i]=='.') s.top()*=1.5;
        }
    }
    double tot=0;
    while(s.size())
    {
        double x=s.top(); s.pop();
        tot+=x;
//      cout<
    }
//  cout<

    printf("%d",(int)(60.0/m*tot));
    return 0;
}
/*
233 1
1-.
g++ calcmu.cpp -o calcmu.exe -Wall

*/

洛谷2622 关灯问题II

本题地址: http://www.luogu.org/problem/show?pid=2622

题目描述

现有n盏灯,以及m个按钮。每个按钮可以同时控制这n盏灯——按下了第i个按钮,对于所有的灯都有一个效果。按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时候,把它关上,否则不管;如果为-1的话,如果这盏灯是关的,那么把它打开,否则也不管;如果是0,无论这灯是否开,都不管。
现在这些灯都是开的,给出所有开关对所有灯的控制效果,求问最少要按几下按钮才能全部关掉。

输入输出格式

输入格式:

前两行两个数,n m
接下来m行,每行n个数,a[i][j]表示第i个开关对第j个灯的效果。

输出格式:

一个整数,表示最少按按钮次数。如果没有任何办法使其全部关闭,输出-1

输入输出样例

输入样例#1:

3
2
1 0 1
-1 1 0

输出样例#1:

2

说明

对于20%数据,输出无解可以得分。
对于20%数据,n<=5
对于20%数据,m<=20
上面的数据点可能会重叠。
对于100%数据 n<=10,m<=100


状压最短路。在这讲过→补丁vs错误

代码:

#include
#include
#include
#include
#include
using namespace std;
const int SIZE=50010;
const int INF=2000000000;
int n,m;

int k[SIZE],g[SIZE];
int dist[SIZE];
bool use[SIZE];
queue<int> q;   
void print(int x)
{
    for(int i=1;i<=5;i++)
    {
        printf("%d",(x>>i)&1);
    }
    cout<<" ";
}
int spfa(int s)
{
    for(int i=0;i<=(1<<(n+1))-1;i++) dist[i]=INF;
    dist[s]=0;
    q.push(s);
    use[s]=1;



    while(q.size())
    {
        int f=q.front(); q.pop();
        use[f]=0;
        for(int i=1;i<=m;i++)
        {
            int v=f;
            v|=g[i];
            v&=(~k[i]);
        //  for(int j=1;j<=n;j++)
        //  {
        //      if(((1<
        //  }
        //  print(f),print(v);print(k[i]);print(g[i]);puts("");
        /// cout<
            if(dist[v]>dist[f]+1)
            {
                dist[v]=dist[f]+1;
                if(!use[v])
                {
                    use[v]=1;
                    q.push(v);
                }
            }
        }
    }
    if(dist[0]==INF) return -1;
    return dist[0];
}



int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);         
            if(x==1) k[i]|=(1<if(x==-1) g[i]|=(1<printf("%d",spfa((1<<(n+1))-2));
    return 0;
}
/*
g++ light.cpp -o light.exe -Wall
*/


洛谷2633 王后万岁

本题地址: http://www.luogu.org/problem/show?pid=2633

题目描述

byteland的王后深受百姓爱戴。为了表达他们的爱,国民们打算占领一个新的国家,并以王后的名字命名。这个国家有n座城市。城市之间有双向道路连接,且每两个城市之间有且仅有一条道路。每座城市对其拥有者来说都有一定的收益。尽管国民们非常爱戴他们的王后,他们并不一定会征服所有的城市献给她。他们只想占领一部分城市(至少有一座),这些城市必须满足两个条件:所有被占领的城市相互间必须是连通的,且城市收益之和最大。你的任务就是算出最大收益是多少。

输入输出格式

输入格式:

第一行是城市的数量n(1<=n<=16000)。第二行包含n个整数,依次表示每座城市的收益,每个数是-1000到1000之间的整数。下面的n-1行描述了道路:每行包含2个整数a和b,用一个空格隔开,表示这两个城市之间有一条道路。

输出格式:

仅有一个数,表示最大收益。

输入输出样例

输入样例#1:

5
-1 1 3 1 -1
4 1
1 3
1 2
4 5

输出样例#1:

4

树上找一块互相连通的区域,使点权和最大。

大概是最水的树形DP了吧……

dp[u]代表选择u号节点时在它子树中的最大权值。

代码:

#include
#include
#include
#include
using namespace std;
const int SIZE=100010;

int n,jz[SIZE];

int head[SIZE],nxt[SIZE],to[SIZE],tot=0;

void build(int f,int t)
{
    to[++tot]=t;
    nxt[tot]=head[f];
    head[f]=tot;
}

int dp[SIZE],ans=0;

void dfs(int u,int fa)
{
    dp[u]=jz[u];
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(v==fa) continue;
        dfs(v,u);
        dp[u]=max(dp[u],dp[u]+dp[v]);
    }
    ans=max(ans,dp[u]);
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&jz[i]);
    }

    for(int i=1;i<=n-1;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        build(a,b);
        build(b,a);
    }

    dfs(1,0);

    printf("%d",ans);
    return 0;
}
/*
g++ queen.cpp -o queen.exe -Wall

9
-3 -2 2 0 1 6 4 5 -4
1 2
1 3
2 4
2 5
2 6
5 7
5 8
5 9

*/

你可能感兴趣的:(===图论===,===数据结构===,===动态规划===,===模拟赛===,最短路,栈/队列,树形DP)