码迷,mamicode.com
首页 > 其他好文 > 详细

11.1 上午考试

时间:2016-11-06 17:03:09      阅读:465      评论:0      收藏:0      [点我收藏+]

标签:ges   stdout   blocks   下一步   span   最短路   0ms   efi   地方   

完美的序列(sequence)
Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 认为一个完美的序列要满足这样的条件:对于任意两个位置上的数都不相同。然而
并不是所有的序列都满足这样的条件。
于是 LYK 想将序列上的每一个元素都增加一些数字(当然也可以选择不增加),使得整个
序列变成美妙的序列。
具体地, LYK 可以花费 1 点代价将第 i 个位置上的数增加 1,现在 LYK 想花费最小的代价
使得将这个序列变成完美的序列。
输入格式(sequence.in)
第一行一个数 n,表示数字个数。
接下来一行 n 个数 ai 表示 LYK 得到的序列。
输出格式(sequence.out)
一个数表示变成完美的序列的最小代价。
输入样例
4
1 1 3 2
输出样例
3
数据范围
对于 30%的数据 n<=5。
对于 60%的数据 n<=1000。
对于 80%的数据 n<=30000, ai<=3000。
对于 100%的数据 n<=100000, 1<=ai<=100000。

/*
要让序列变成一个不含相同元素的
首先排序
排完序后只需让序列变成一个严格上升的序列
现在让a[i]=a[i]-i
这样处理后只需让序列变成一个不降序列就保证了原序列是上升序列 
(因为a[i]比a[i-1]多减了1,只需a[i]不比a[i-1]小即可)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,ans;
int a[maxn];
int init()
{
    int x=0,f=1;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int main()
{
    freopen("sequence.in","r",stdin);
    freopen("sequence.out","w",stdout);
    n=init();
    for(int i=1;i<=n;i++)
      a[i]=init();
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
      a[i]-=i;
    for(int i=2;i<=n;i++)
    {
        if(a[i]>=a[i-1])continue;
        ans+=a[i-1]-a[i];
        a[i]=a[i-1];
    }
    printf("%d\n",ans);
    return 0;
} 

 


LYK 与实验室(lab)
Time Limit:5000ms Memory Limit:64MB
题目描述
LYK 在一幢大楼里,这幢大楼共有 n 层, LYK 初始时在第 a 层上。
这幢大楼有一个秘密实验室,在第 b 层,这个实验室非常特别,对 LYK 具有约束作用,
即若 LYK 当前处于 x 层,当它下一步想到达 y 层时,必须满足|x-y|<|x-b|,而且由于实验室
是不对外开放的,电梯无法停留在第 b 层。
LYK 想做一次旅行,即它想按 k 次电梯,它想知道不同的旅行方案个数有多少个。
两个旅行方案不同当前仅当存在某一次按下电梯后停留的楼层不同。
输入格式(lab.in)
一行 4 个数, n,a,b,k。
输出格式(lab.out)
一个数表示答案,由于答案较大,将答案对 1000000007 取模后输出。
输入样例 1
5 2 4 1
输出样例 1
2
输入样例 2
5 2 4 2
输出样例 2
2
输入样例 3
5 3 4 1
输出样例 3
0
数据范围
对于 20%的数据 n,k<=5。
对于 40%的数据 n,k<=10。
对于 60%的数据 n,k<=500。
对于 90%的数据 n,k<=2000。
对于 100%的数据 n,k<=5000。

技术分享
/*
dp O(n^3)
超时 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define maxn 5010
using namespace std;
int n,w,a,b,ans;
int dp[2][maxn];
int init()
{
    int x=0,f=1;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int abs(int x)
{
    return x>=0?x:-x;
}
int main()
{
    freopen("lab.in","r",stdin);
    freopen("lab.out","w",stdout);
    n=init();a=init();b=init();w=init();
    for(int i=1;i<=n;i++)dp[w+1&1][i]=1;
    for(int i=w;i>=1;i--)
    {
        for(int j=1;j<=n;j++)
          dp[i&1][j]=0;
        for(int j=1;j<=n;j++)
        {
            for(int k=1;k<=n;k++)
            {
                if(k==b||k==j)continue;
                if(abs(j-k)<abs(j-b))
                dp[i&1][j]=(dp[i&1][j]+dp[i+1&1][k])%mod;
            }
        }
    }
    printf("%d\n",dp[1&1][a]);
    return 0;
}
View Code

 

/*
搜索-->记忆化搜索-->dp O(n^3)-->dp O(n^2)
dp状态
dp[i][j]表示第i次停在j的方案数
倒推 边界为dp[w+1][j]=1(j!=b)
因为最后可以停在除了b的所有地方
dp[i][j]+=dp[i+1][k](abs(j-k)<abs(j-b))
本来应该循环但超时
令x=abs(j-b) 
 abs(j-k)<x
 -x<j-k<x
 j-x<k<j+x
维护i+1的前缀和可以O(1)查出dp[i+1][j-x]到dp[i+1][j+x]得和
注意不能停在原楼层 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
#define maxn 5010
using namespace std;
int n,w,a,b,ans;
int dp[2][maxn];
int sum[maxn];
int init()
{
    int x=0,f=1;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int abs(int x)
{
    return x>=0?x:-x;
}
int main()
{
    freopen("lab.in","r",stdin);
    freopen("lab.out","w",stdout); 
    n=init();a=init();b=init();w=init();
    for(int i=1;i<=n;i++)
    {
        if(i!=b)dp[w+1&1][i]=1;
        sum[i]=(sum[i-1]+dp[w+1&1][i])%mod;
    }  
    for(int i=w;i>=1;i--)
    {
        for(int j=1;j<=n;j++)
          dp[i&1][j]=0;
        for(int j=1;j<=n;j++)
        {
            if(j==b)continue;
            int cha=abs(j-b)-1;int l=max(0,j-cha),r=min(n,j+cha);
            if(l>r)continue;
            dp[i&1][j]=((sum[r]-sum[l-1])%mod+mod)%mod;
            dp[i&1][j]=((dp[i&1][j]-dp[i+1&1][j])%mod+mod)%mod;
        }
        for(int j=1;j<=n;j++)
          sum[j]=(sum[j-1]+dp[i&1][j])%mod;
    }
    printf("%d\n",dp[1&1][a]);
    return 0;
}

 

旅行(travel)
Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 想去一个国家旅行。这个国家共有 n 个城市,有些城市之间存在道路,我们假定这
些道路长度都是 1 的,更准确的说,共有 m 条道路。
我们定义城市 A 与城市 B 的最短路为 A 到 B 的所有路径中,经过的道路最少的那条道
路。最短路的长度为这条道路的所有道路长度之和,由于所有道路长度都为 1,因此假如 A
到 B 之间最短路的道路条数为 k,则 A 到 B 的最短路长度为 k。
我们定义整个国家的最短路为任意两个城市( A,B 与 B,A 算作不同的点对)之间的最短
路长度的和。
然而这个国家正处于危乱之中,极有可能一条道路会被恐怖分子炸毁。
LYK 想知道,万一某条道路被炸毁了,整个国家的最短路为多少。若炸毁这条道路后整
个国家不连通了,那么就输出“ INF” (不加引号)。
输入格式(travel.in)
第一行两个数 n,m。
接下来 m 行,每行两个数 u,v,表示存在一条道路连接 u,v(数据保证不存在自环)。
输出格式(travel.out)
输出 m 行,第 i 行的值表示当第 i 条道路被炸毁时,整个国家的最短路是多少,若图不
连通,则输出“ INF”。
输入样例
2 2
1 2
1 2
输出样例
2 2
数据范围
对于 20%的数据 n<=10,n<m<=100。
对于 40%的数据 1<=n<m<=100。
对于 70%的数据 1<=n<=100,n<m<=3000。
对于再另外 10%的数据对于所有节点( i 1<=i<n),存在一条边连接 i与 i+1,且 n=m,n<=100。
对于再再另外 10%的数据对于所有节点 i( 1<=i<n),存在一条边连接 i 与 i+1,且 n=m,
n<=1000。
对于再再再另外 10%的数据对于所有节点( i 1<=i<n),存在一条边连接 i 与 i+1,且 n=m,
n<=100000。

暂无正解

11.1 上午考试

标签:ges   stdout   blocks   下一步   span   最短路   0ms   efi   地方   

原文地址:http://www.cnblogs.com/dingmenghao/p/6035390.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!