题目:
描述
一年一度的“跳石头”比赛又要开始了!
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石)。
格式
输入格式
输入第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终 点之间的岩石数,以及组委会至多移走的岩石数。
接下来 N 行,每行一个整数,第 i 行的整数 DiDi
(0<Di<L0<Di<L
)表示第 ii
块岩石与 起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同 一个位置。
输出格式
输出只包含一个整数,即最短跳跃距离的最大值。
限制
对于20%的数据,0≤M≤N≤100≤M≤N≤10
。
对于50%的数据,0≤M≤N≤1000≤M≤N≤100
。
对于100%的数据,0≤M≤N≤500000≤M≤N≤50000
,1≤L≤10000000001≤L≤1000000000
。
提示
对于样例。将与起点距离为 2 和 14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。
描述
有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出的位置不同也认为是不同的方案。
格式
输入格式
第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问 题描述中所提到的 k,每两个整数之间用一个空格隔开。第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。
输出格式
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输 出答案对 1,000,000,007 取模的结果。
限制
对于第 1 组数据:1≤n≤500,1≤m≤50,k=1;
对于第 2 组至第 3 组数据:1≤n≤500,1≤m≤50,k=2;
对于第 4 组至第 5 组数据:1≤n≤500,1≤m≤50,k=m;
对于第 1 组至第 7 组数据:1≤n≤500,1≤m≤50,1≤k≤m;
对于第 1 组至第 9 组数据:1≤n≤1000,1≤m≤100,1≤k≤m;
对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m。
提示
样例 1:aab aab / aab aab
样例 2:a ab aab / a aba ab / a a ba ab / aab a ab
aa b aab / aa baa b / aab aa b
样例 3:a a b aab / a a baa b / a ab a a b / a aba a b
a a b a a b / a a ba a b / aab a a b
描述
公元 2044 年,人类进入了宇宙纪元。L 国有 nn
个星球,还有 n−1n−1
条双向航道,每条航道建立在两个星球之间,这 n−1n−1
条 航道连通了 L 国的所有星球。
小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物 流飞船需要从 uiui
号星球沿最快的宇航路径飞行到 vivi
号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 jj
,任意飞船驶过它所花费的时间为 tjtj
,并且任意两艘飞船之间不会产生任何干扰。
为了鼓励科技创新,L 国国王同意小 PP
的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了 mm
个运输计划。在虫洞建设完成后, 这 mm
个运输计划会同时开始,所有飞船一起出发。当这 mm
个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。
如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
格式
输入格式
第一行包括两个正整数 nn
、mm
,表示 L 国中星球的数量及小 P 公司预接的运输计划的 数量,星球从 11
到 nn
编号。
接下来 n−1n−1
行描述航道的建设情况,其中第 ii
行包含三个整数 aiai
, bibi
和 titi
,表示第 ii
条双向航道修建在 aiai
与 bibi
两个星球之间,任意飞船驶过它所花费的时间为 titi
。
接下来 mm
行描述运输计划的情况,其中第 jj
行包含两个正整数 ujuj
和 vjvj
,表示第 jj
个 运输计划是从ujuj
号星球飞往 vjvj
号星球。
输出格式
共 1 行,包含 1 个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
限制
一共有20组数据。
其中n的取值依次为:100,100,100,2000,1000,2000,3000,1000,2000,3000,80000,100000,70000,80000,90000,100000,80000,90000,100000,300000。
其中m的取值依次为:1,100,100,1,1000,2000,3000,1000,2000,3000,1,1,70000,80000,90000,100000,80000,90000,100000,300000。
其中第2,5,6,7,13,14,15,16组数据满足:第 i 条航道连接 i 号星球与 i+1 号星球。
提示
输入输出样例 1 说明。
将第 1 条航道改造成虫洞:则三个计划耗时分别为:11、12、11,故需要花费的时 间为 12。
将第 2 条航道改造成虫洞:则三个计划耗时分别为:7、15、11,故需要花费的时 间为 15。
将第 3 条航道改造成虫洞:则三个计划耗时分别为:4、8、11,故需要花费的时间 为 11。
将第 4 条航道改造成虫洞:则三个计划耗时分别为:11、15、5,故需要花费的时 间为 15。
将第 5 条航道改造成虫洞:则三个计划耗时分别为:11、10、6,故需要花费的时 间为 11。
故将第 3 条或第 5 条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花 费的时间为 11。
解题报告:
第一题:先开始的时候,看见的时候觉得是贪心,然后又觉得有反例,就没敢写,然后就开始暴搜,只有10分。。
这里有一个套路,就是在最小中求最大,或者最大中最小,就想到二分。一定要形成条件反射,想不到方法,就试一试二分可不可以解决。这里因为总长度是确定的,所以可以二分答案,然后判断不满足此长度的点(即与前一个点的距离小于该长度,这里有一个更新last,只有当删了一个节点时才更新,所以代码里是有一个else)如果个数大于m,就取左区间。注意二分的模板和 判重 。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 50005 6 using namespace std; 7 int n,m,l,li,ri,ans; 8 int a[maxn]; 9 bool pd(int x) 10 { 11 int last=0,sum=0; 12 for (int i=1;i<=n+1;i++)// n+1 13 { 14 if (a[i]-last<x) sum++; 15 else last=a[i];//只有在不取的时候更新last 16 } 17 if (sum>m) return 0; 18 return 1; 19 } 20 int main() 21 { 22 freopen("stone.in","r",stdin); 23 freopen("stone.out","w",stdout); 24 cin>>l>>n>>m; 25 for (int i=1;i<=n;i++) 26 scanf("%d",&a[i]); 27 a[n+1]=l; 28 li=1;ri=l; 29 while (li<ri){ 30 int mid=(li+ri)>>1; 31 if (pd(mid)) { 32 //ans=mid; 33 li=mid+1; 34 } 35 else ri=mid; 36 } 37 if (pd(l)) ans=l;//注意特判 38 else ans=li-1; 39 cout<<ans; 40 return 0; 41 }
第二题:动态规划。但是我就是这一块不熟,一般动规的题我都不会做。然后这道题理解起来就比较困难。代码贴在这里,解析我觉得这位写的不错:http://blog.csdn.net/XianHaoMing/article/details/51222553 还有滚动数组的思想也需要注意。如果看不懂得话,就看这位的吧:http://www.cnblogs.com/ivorysi/p/5804685.html 我就直接上代码了。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define maxn 1005 6 #define inf 1000000000+7 7 using namespace std; 8 int n,m,k,cur,last; 9 string s1,s2; 10 int s[maxn][205][3],f[maxn][205][3];//s[i][j][k] A 11 int main() 12 { 13 freopen("substring.in","r",stdin); 14 freopen("substring.out","w",stdout); 15 cin>>n>>m>>k; 16 cin>>s1;cin>>s2; 17 for (int i=0;i<=n;i++) s[i][0][0]=1;//初值 18 cur=0;last=1; 19 for (int ki=1;ki<=k;ki++) 20 { 21 swap(cur,last);//滚动数组 22 for (int j=ki;j<=m;j++) 23 for (int i=j;i<=n;i++) 24 { 25 if (s1[i-1]==s2[j-1]) 26 { 27 f[i][j][cur]=f[i-1][j-1][cur]+s[i-1][j-1][last]; 28 f[i][j][cur]%=inf; 29 f[i-1][j-1][cur]=0; 30 } 31 else f[i][j][cur]=0; 32 s[i][j][cur]=f[i][j][cur]+s[i-1][j][cur]; 33 s[i][j][cur]%=inf; 34 } 35 } 36 cout<<s[n][m][cur]; 37 return 0; 38 }
第三题:正解是:LCA+树剖+二分+差分序列。但是我并不想做。所以乱搞了一个30分的代码,但是话说这个代码不应该是60分吗?下次来看哪里有问题。
看来数据分治很好用啊。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #define maxn 100005 6 using namespace std; 7 int n,m,v[maxn],s[maxn],su[maxn],ma=0,sum[maxn],ans,bb; 8 int tot,he[maxn],ne[maxn*2],to[maxn*2],w[maxn*2],st,en; 9 bool vis[maxn]; 10 void add(int a,int b,int c) 11 { 12 tot++;ne[tot]=he[a];to[tot]=b;w[tot]=c;he[a]=tot; 13 } 14 void dfs(int x,int cur,int suu) 15 { 16 if (x==en) { 17 ans=suu-cur; 18 return ; 19 } 20 for (int i=he[x];i;i=ne[i]) 21 if (!vis[to[i]]){ 22 vis[to[i]]=1; 23 if (w[i]>cur) dfs(to[i],w[i],suu+w[i]); 24 else dfs(to[i],cur,suu+w[i]); 25 } 26 } 27 int main() 28 { 29 freopen("transport.in","r",stdin); 30 freopen("transport.out","w",stdout); 31 cin>>n>>m; 32 if (m!=1){//处理 链 的情况 33 for (int i=1;i<n;i++){ 34 int a,b,c; 35 scanf("%d%d%d",&a,&b,&c); 36 v[a]=c; 37 sum[a]=sum[a-1]+v[a]; 38 } 39 for (int i=1;i<=m;i++) 40 { 41 int a,b; 42 scanf("%d%d",&a,&b); 43 s[a]++;s[b]--; 44 if (sum[b-1]-sum[a-1]>ma) ma=sum[b-1]-sum[a-1]; 45 } 46 memset(sum,0,sizeof(sum)); 47 for (int i=1;i<=n;i++) 48 { 49 sum[i]=sum[i-1]+s[i]; 50 if (v[i]*sum[i]>ans) { 51 ans=v[i]*sum[i]; 52 bb=i; 53 } 54 } 55 cout<<ma-v[bb]; 56 } 57 else { 58 for (int i=1;i<n;i++) 59 { 60 int a,b,c; 61 scanf("%d%d%d",&a,&b,&c); 62 add(a,b,c); 63 add(b,a,c); 64 } 65 scanf("%d%d",&st,&en); 66 vis[st]=true; 67 dfs(st,0,0); 68 cout<<ans; 69 } 70 return 0; 71 }
滚回去看动规了。。。