这场比赛失误了,要是有同学也是一起比赛的,希望就别打我脸了,我写博客也是需要勇气的,其中里面真的好几题都不会。涉及到dp的都懵B。怪自己不认真学习。
棋盘游戏,和回文路真的看题解之后才有点悟性。
问题 A: 垃圾陷阱
时间限制: 1 Sec 内存限制: 128 MB提交: 79 解决: 39
[ 提交][ 状态][ 讨论版]
题目描述
卡门想把垃圾堆起来,等到堆得与井同样高时,她就能逃出井外了。另外,卡门可以通过吃一些垃圾来维持自己的生命。
每个垃圾都可以用来吃或堆放,并且堆放垃圾不用花费卡门的时间。
假设卡门预先知道了每个垃圾扔下的时间t(0<t<=1000),以及每个垃圾堆放的高度h(1<=h<=25)和吃进该垃圾能维持生命的时间f(1<=f<=30),要求出卡门最早能逃出井外的时间,假设卡门当前体内有足够持续10小时的能量,如果卡门10小时内没有进食,卡门就将饿死。
输入
第二到第G+1行每行包括3个整数:T (0 < T <= 1000),表示垃圾被投进井中的时间;F (1 <= F <= 30),表示该垃圾能维持卡门生命的时间;和 H (1 <= H <= 25),该垃圾能垫高的高度。
输出
样例输入
20 4
5 4 9
9 3 2
12 6 10
13 1 1
样例输出
13
提示
卡门堆放她收到的第一个垃圾:height=9;
卡门吃掉她收到的第二个垃圾,使她的生命从10小时延伸到13小时;
卡门堆放第3个垃圾,height=19;
卡门堆放第4个垃圾,height=20。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct point{
int t,f,h;
}p;
p a[1005];
int f[1005];
int cmp(p x,p y){
return x.t<y.t;
}
int main()
{
int D,T,G;
cin>>D>>G;
for(int i=1;i<=G;i++){
cin>>a[i].t>>a[i].f>>a[i].h;
}
sort(a+1,a+G+1,cmp);
f[0]=10;
for(int i=1;i<=G;i++){
for(int j=D;j>=0;j--){
if(f[j]>=a[i].t){
if(j+a[i].h>=D){
printf("%d\n",a[i].t);
return 0;
}
f[j+a[i].h]=max(f[j+a[i].h],f[j]);
f[j]+=a[i].f;
}
}
}
printf("%d\n",f[0]);
return 0;
}
问题 B: 低价购买
时间限制: 1 Sec 内存限制: 128 MB提交: 173 解决: 64
[ 提交][ 状态][ 讨论版]
题目描述
这里是某支股票的价格清单:
日期 1 2 3 4 5 6 7 8 9 10 11 12
价格 68 69 54 64 68 64 70 67 78 62 98 87
最优秀的投资者可以购买最多4次股票,可行方案中的一种是:
日期 2 5 6 10
价格 69 68 64 62
输入
第2行: N个数,是每天的股票价格。
输出
样例输入
12
68 69 54 64 68 64 70 67 78 62 98 87
样例输出
4 2
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<string>
#include<sstream>
using namespace std;
int main()
{
int n,a[5050],dp[5050]={0},g[5050]={0};
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int maxz=1;
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]>a[i])
dp[i]=max(dp[j]+1,dp[i]);
maxz=max(maxz,dp[i]);
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]<a[j]&&dp[j]+1==dp[i]){
g[i]+=g[j];
}
}for(int j=1;j<i;j++){
if(a[i]==a[j]&&dp[i]==dp[j]){
g[j]=0;
}
}
if(dp[i]==1){
g[i]=1;
}
}
for(int i=1;i<=n;i++){
if(dp[i]==maxz){
ans+=g[i];
}
}
printf("%d %d\n",maxz,ans);
}
问题 C: 奇怪的电梯
时间限制: 1 Sec 内存限制: 64 MB提交: 166 解决: 60
[ 提交][ 状态][ 讨论版]
题目描述
输入
第2行为N个正整数,表示Ki。
输出
样例输入
5 1 5
3 3 1 2 5
样例输出
3
提示
上述答案得到方式如下:
从1楼按上,上到4楼
在4楼按下,到达2楼
在2楼按上,到达5楼
共3步
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
typedef struct point{
int x,step;
}p;
int a[220],n,A,B;
int vis[220];
int bfs()
{
p first;
first.x=A;
first.step=0;
queue<p>q;
q.push(first);
while(!q.empty()){
p cur=q.front();
q.pop();
if(cur.x==B){
return cur.step;
}
vis[cur.x]=1;
for(int i=1;i<=2;i++){
if(i==1){
p next;
next.step=cur.step+1;
int t=cur.x;
if(t+a[t]<=n&&a[t]!=0&&vis[t+a[t]]!=1){
next.x=t+a[t];
q.push(next);
}
}else if(i==2){
p next;
next.step=cur.step+1;
int t=cur.x;
if(t-a[t]>=1&&a[t]!=0&&vis[t-a[t]]!=1){
next.x=t-a[t];
q.push(next);
}
}
}
}
return -1;
}
int main()
{
scanf("%d%d%d",&n,&A,&B);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int ans=bfs();
printf("%d\n",ans);
return 0;
}
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <map>
const int N = 50050;
const int p[20] = {
2, 3, 5, 7, 11,
13, 17, 19, 23, 29,
31, 37, 41, 43, 47,
53, 59, 61, 67, 71
};
double logp[20];
double f[505][20];
int d[505];
int cnt;
int A[100000], len;
void mul(int x) {
int v = 0;
for (int i = 0; i < len; ++i) {
v = (A[i] = A[i] * x + v) / 10;
A[i] %= 10;
}
while (v) A[len++] = v % 10, v /= 10;
}
int main() {
int n, m = 0;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) if (!(n % i)) d[m++] = i;
for (int i = 0; i < 20; ++i) f[0][i] = .0;
for (int i = 0; i < 20; ++i) logp[i] = log(p[i]);
for (int i = 1; i < m; ++i) {
for (int k = 0; k < 20; ++k)
f[i][k] = 1e9;
for (int j = 0; j < i; ++j) if (!(d[i] % d[j])) {
int t = d[i] / d[j];
for (int k = 1; k < 20; ++k)
f[i][k] = std::min(f[i][k], f[j][k - 1] + logp[k - 1] * (t - 1));
}
}
A[0] = len = 1;
int j = 0;
for (int i = 0; i < 20; ++i) if (f[m - 1][i] < f[m - 1][j]) j = i;
for (int i = m - 1, nxt; i; i = nxt, --j) {
for (nxt = 0; d[i] % d[nxt] || f[i][j] < f[nxt][j - 1]
+ logp[j - 1] * (d[i] / d[nxt] - 1) - 1e-5; ++nxt);
for (int k = 1; k < d[i] / d[nxt]; ++k)
mul(p[j - 1]);
}
while (len--) printf("%d", A[len]);
return 0;
}
问题 E: 棋盘游戏
时间限制: 5 Sec 内存限制: 128 MB提交: 20 解决: 10
[ 提交][ 状态][ 讨论版]
题目描述
Klux说:“这么简单的题目,我都会做!”
输入
接着是一个空行。
第6到9行每行四个数字,描述了最终棋盘。
输出
接下来n行每行4个数,r1,c1,r2,c2,表示移动的两个棋子的坐标(r1,c1),(r2,c2)(棋盘左上角的坐标为(1,1),并且他右边的格子为(1,2))
如果有许多组解,你可以输出任意一组。
样例输入
1111
0000
1110
0010
1010
0101
1010
0101
样例输出
4
1 2 2 2
1 4 2 4
3 2 4 2
4 3 4 4
#include<stdio.h>
#include<iostream>
#include<queue>
using namespace std;
typedef struct point{
int x,step;
}p;
int A,B;
int vis[210000];
void bfs()
{
queue<p>q;
q.push((p){A,0});
while(!q.empty()){
p cur=q.front();
q.pop();
int tmp=cur.x;
if(tmp==B){
cout<<cur.step<<endl;
return ;
}
for(int i=15;i>=0;i--){
int x=(15-i)/4,y=(15-i)%4,w=1<<i,z;
if(y<3&&(tmp&(1<<i))!=(tmp&(1<<i-1))){
z=1<<i-1;
if(!vis[tmp^z^w]){
vis[tmp^z^w]=1;
q.push((p){tmp^z^w,cur.step+1});
}
}
if(x<3&&(tmp&(1<<i))!=(tmp&(1<<i-4))){
z=1<<i-4;
if(!vis[tmp^z^w]){
vis[tmp^z^w]=1;
q.push((p){tmp^z^w,cur.step+1});
}
}
}
}
}
int main()
{
char c;
for(int i=15;i>=0;i--){
cin>>c;
if(c!='0')
A+=1<<i;
}
for(int i=15;i>=0;i--){
cin>>c;
if(c!='0')
B+=1<<i;
}
if(A==B)cout<<0<<endl;
else bfs();
}
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=1<<17;
int n,m,k,r,vis[maxn],pre[maxn];
typedef struct point{
int prex,prey,x,y;
}node;
node ans[maxn];
queue<int>p;
void dfs(int now){
if(ans[pre[now]].x)dfs(pre[now]);
printf("%d %d %d %d\n",ans[now].x,ans[now].y,ans[now].prex,ans[now].prey);
}
int main()
{
int j;
for(int i=0;i<=15;i++){
scanf("%1d",&j),n+=j*(1<<i);
}vis[n]=1;p.push(n);
for(int i=0;i<=15;i++){
scanf("%1d",&j),m+=j*(1<<i);
}
if(n==m){
return 0*puts("0");
}
while(!p.empty())
{
int q=p.front();p.pop();
for(int i=0;i<=11;i++)
{
int u=((q&(1<<i))>>i),v=((q&(1<<i+4))>>(i+4));
if(u!=v)
{
int r=q+((1<<i+4)-(1<<i))*(u-v);
if(!vis[r])
{
p.push(r);
ans[r].prex=i/4+1;
ans[r].prey=i%4+1;
ans[r].x=(i+4)/4+1;
ans[r].y=(i+4)%4+1;
pre[r]=q;
vis[r]=vis[q]+1;
if(r==m)goto loop;
}
}
}
for(int i=0;i<=15;i++)
{
if(i%4==3)continue;
int u=((q&(1<<i))>>i),v=((q&(1<<i+1))>>(i+1));
if(u!=v)
{
int r=q+((1<<i+1)-(1<<i))*(u-v);
if(!vis[r])
{
p.push(r);
ans[r].prex=i/4+1;
ans[r].prey=i%4+1;
ans[r].x=(i+1)/4+1;
ans[r].y=(i+1)%4+1;
pre[r]=q;
vis[r]=vis[q]+1;
if(r==m)goto loop;
}
}
}
}
loop:;
printf("%d\n",vis[m]-1);
dfs(m);
return 0;
}
问题 F: 连续自然数和
时间限制: 1 Sec 内存限制: 128 MB提交: 266 解决: 83
[ 提交][ 状态][ 讨论版]
题目描述
例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。
输入
输出
样例输入
10000
样例输出
18 142
297 328
388 412
1998 2002
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstdio>
using namespace std;
int main()
{
int n;
cin>>n;
int len=(int)sqrt(2*n);
for(int i=len;i>=2;i--){
int a=(((n*2)/i)+(1-i))/2;
if((a+(a+i-1))*i==2*n){
printf("%d %d\n",a,a+i-1);
}
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
typedef long long ll;
using namespace std;
int main()
{
long long int n;
cin>>n;
for(ll a=1;a<n;a++){
ll b=-0.5+sqrt(2*n-a+a*a+0.25);
if((a+b)*(b-a+1)==2*n){
printf("%d %lld\n",a,b);
}
}
return 0;
}
问题 G: Fence Painting
时间限制: 1 Sec 内存限制: 64 MB提交: 195 解决: 76
[ 提交][ 状态][ 讨论版]
题目描述
If we regard the fence as a one-dimensional number line, Farmer John paints the interval between x=a
and x=b. For example, if a=3 and b=5, then Farmer John paints an interval of length 2. Bessie, misunderstanding Farmer John's instructions, paints the interval from x=c to x=d, which may possibly overlap with part or all of Farmer John's interval. Please determine the total length of fence that is now covered with paint.
输入
The second line contains integers c and d, separated by a space (c<d ).
The values of a , b, c, and d all lie in the range 0…100, inclusive.
输出
样例输入
7 10
4 8
样例输出
6
提示
Here, 6 total units of fence are covered with paint, from x=4 all the way through x=10.
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int main()
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
if(b<c||d<a){
int ans=b-a+d-c;
printf("%d\n",ans);
}else{
int t1=min(a,c),t2=max(b,d);
int ans=t2-t1;
printf("%d\n",ans);
}
return 0;
}
问题 H: Speeding Ticket
时间限制: 1 Sec 内存限制: 64 MB提交: 117 解决: 53
[ 提交][ 状态][ 讨论版]
题目描述
The road is exactly 100 miles long, and Bessie drives the entire length of the road before ultimately being pulled over by a police officer, who gives Bessie a ticket for exceeding the speed limit, for having an expired license, and for operating a motor vehicle while being a cow. While Bessie concedes that the last two tickets are probably valid, she questions whether the police officer was correct in issuing the speeding ticket, and she wants to determine for herself if she has indeed driven faster than the speed limit for part of her journey.
The road is divided into N segments, each described by a positive integer length in miles, as well as an integer speed limit in the range 1…100 miles per hour. As the road is 100 miles long, the lengths of all N segments add up to 100. For example, the road might start with a segment of length 45 miles, with speed limit 70, and then it might end with a segment of length 55 miles, with speed limit 60.
Bessie's journey can also be described by a series of segments, M of them. During each segment, she travels for a certain positive integer number of miles, at a certain integer speed. For example, she might begin by traveling 50 miles at a speed of 65, then another 50 miles at a speed of 55. The lengths of all M segments add to 100 total miles. Farmer John's tractor can drive 100 miles per hour at its fastest.
Given the information above, please determine the maximum amount over the speed limit that Bessie travels during any part of her journey.
输入
The next N lines each contain two integers describing a road segment, giving its length and speed limit.
The next M lines each contain two integers describing a segment in Bessie's journey, giving the length and also the speed at which Bessie was driving.
输出
样例输入
3 3
40 75
50 35
10 45
40 76
20 30
40 40
样例输出
5
提示
In this example, the road contains three segments (40 miles at 75 miles per hour, followed by 50 miles at 35 miles per hour, then 10 miles at 45 miles per hour). Bessie drives for three segments (40 miles at 76 miles per hour, 20 miles at 30 miles per hour, and 40 miles at 40 miles per hour). During her first segment, she is slightly over the speed limit, but her last segment is the worst infraction, during part of which she is 5 miles per hour over the speed limit. The correct answer is therefore 5.
#include<stdio.h>
#include<algorithm>
using namespace std;
typedef struct point{
int lim,x;
}p;
p len[1000];
int suma[1000],sumb[1000];
int main()
{
int n,m,a[1000],b[1000],suma[1000],sumb[1000];
scanf("%d%d",&n,&m);
a[0]=0,b[0]=0;
suma[0]=0,sumb[0]=0;
for(int i=1;i<=n;i++){
int limt;
scanf("%d%d",&a[i],&limt);
suma[i]=a[i]+suma[i-1];
for(int j=suma[i-1];j<=suma[i];j++){
len[j].lim=limt;
}
}
for(int i=1;i<=m;i++){
int t;
scanf("%d%d",&b[i],&t);
sumb[i]=b[i]+sumb[i-1];
for(int j=sumb[i-1];j<=sumb[i];j++){
len[j].x=t;
}
}
int maxz=-1;
for(int i=0;i<=100;i++){
maxz=max(maxz,len[i].x-len[i].lim);
}
if(maxz<=0){
printf("0\n");
}else{
printf("%d\n",maxz);
}
}
问题 J: Palindromic Paths
时间限制: 1 Sec 内存限制: 64 MB提交: 18 解决: 3
[ 提交][ 状态][ 讨论版]
题目描述
ABCD
BXZX
CDXB
WCBA
Each day, Bessie the cow walks from the upper-left field to the lower-right field, each step taking her either one field to the right or one field downward. Bessie keeps track of the string that she generates during this process, built from the letters she walks across. She gets very disoriented, however, if this string is a palindrome (reading the same forward as backward), since she gets confused about which direction she had walked.
Please help Bessie determine the number of distinct routes she can take that correspond to palindromes. Different ways of obtaining the same palindrome count multiple times. Please print your answer modulo 1,000,000,007.
输入
输出
样例输入
4
ABCD
BXZX
CDXB
WCBA
样例输出
12
提示
Bessie can make the following palindromes
1 x "ABCDCBA"
1 x "ABCWCBA"
6 x "ABXZXBA"
4 x "ABXDXBA"
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
char s[502][502];
ll dp[502][502][2];
int main() {
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%s",s[i]+1);
int now=1,pre=0;
if(s[1][1]!=s[n][n]) {
return 0,printf("0\n");
}
dp[1][n][pre]=1;
for(int k=2; k<=n; k++) {
for(int i=1; i<=k; i++)
for(int j=n; j>=i&&j>=n-k+1; j--) {
if(s[i][k-i+1]==s[j][n-k+n-j+1])
dp[i][j][now]=(dp[i-1][j][pre]+dp[i][j][pre]+dp[i][j+1][pre]+dp[i-1][j+1][pre])%mod;
else dp[i][j][now]=0;
}
swap(now,pre);
}
ll ans=0;
for(int i=1; i<=n; i++) {
ans=(ans+dp[i][i][pre])%mod;
}
printf("%lld",ans);
return 0;
}