Glory And String
时间限制: 1 Sec 内存限制: 128 MB
题目描述
输入
First line is the number of strings T, the T lines follow, each line describe a string Glory needs to operate.The total length of strings won't exceed 5,000 and consist of only lower-case characters.The length of each string won't exceed 2,000.
输出
样例输入
3
aaaab
abcde
abb
样例输出
1
4
1
把原串反过来跟原串做一次最长公共子序列,原串总长减去最长公共子序列就是答案。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 5 * 1e3 + 5;
int dp[2][maxn];
char a[maxn],a1[maxn],c[maxn];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
int ans = -1;
scanf(" %s",a + 1);
strcpy(c,a + 1);
n = strlen(c);
for(int i = 0;i <= n + 1; ++i) dp[0][i] = dp[1][i] = 0;
for(int i = 1;i <= n; ++i) a1[i] = a[n + 1 - i];
a1[0] =' ',a1[n + 1] = '\0';
for(int i = 1;i <= n; ++i)
{
for(int j = 1;j <= n; ++j)
{
if(a[i] == a1[j]) dp[i % 2][j] = dp[(i - 1) % 2][j - 1] + 1;
else dp[i % 2][j] = max(dp[(i - 1) % 2][j],dp[i % 2][j - 1]);
ans = max(ans,dp[i % 2][j]);
}
}
printf("%d\n",n - ans);
}
return 0;
}
W老师的玩具
时间限制: 2 Sec 内存限制: 128 MB
题目描述
由于不小心让W老师在某道题上卡了十几发,A给W老师买了个玩具以表示歉意.
这个玩具可以看做一个多重集
最初,集合中只有一个元素0
每一轮,W老师会操作其中的每一个元素(设当前操作的为x)执行以下三种操作之一:
1. x=x+1
2. x分裂成两个非负整数a,b 即x=a+b,且a>=0,b>=0
3. 什么也不做
W老师玩了很久之后,已经不记得自己玩了多少轮了.
他很好奇自己最少玩多少轮才能把集合从开始变成现在的状态.
于是他把这个任务交给了A,如果A能找到答案他就会选择原谅他.但是A实在是太菜了,你能帮帮A吗?
输入
第一行,一个整数N,表示最终集合的大小
第二行为N个非负整数,表示最终集合的每一个元素
输出
一行,W老师最少玩的轮数
样例输入
4
1 1 1 1
样例输出
3
提示
单组数据
N<=1,000,000
0<=集合里的数字<=1,000,000
样例解释
第一轮:
0分裂成0 0
第二轮
0 0中每个0分裂成两个0,得到0 0 0 0
第三轮
每个0+1,得到1 1 1 1
逆序模拟一下即可,代码中体会吧。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 1e6 + 5;
int a[maxn];
bool cmp(int x,inty)
{
returnx > y;
}
int main()
{
int n;
scanf("%d",&n);
a[0] = -1;
for(int i = 1;i <= n; ++i) scanf("%d",&a[i]);
sort(a + 1,a + n + 1,cmp);
int ans = 0;
int loc = n,num0 = 0;
int temp = a[n],cal = a[n];
while(loc > 0)
{
temp = a[loc] - a[loc + 1];
for(int i = 0;loc > 0 && i < temp && num0 > 1; ++i)
{
if(num0 & 1) ++num0;
num0 >>= 1;
}
ans += temp;
while(a[loc] == a[loc - 1]) --loc, ++num0;
++num0;
--loc;
}
while(num0 > 1)
{
if(num0 & 1) ++num0;
num0 >>= 1;
++ans;
}
printf("%d\n",ans);
return 0;
}
尧老师要教孩子玩球球
时间限制: 2 Sec 内存限制: 128 MB
题目描述
尧老师总是被他女朋友抱怨:还在玩ACM,玩个球啊!所以今天他和他的孩子要去房顶玩球。他们有 n 个球,半径分别为 ri。现将它们完全装入了内径为 R 的烟囱(假设烟囱内部为圆柱),问烟囱高最小为多少。
输入
第一行包含一个整数 n (0 <= n <= 18)。
第二行包含 n 个整数 ri (0 < ri <= 1e4)。.
第三行包含一个整数 R(max(ri)<= R < 2 * min( ri ))。
输出
输出烟囱最小高度,保留两位小数。
样例输入
2
2 3
3
样例输出
9.90
正解是DP,打表找规律侥幸过了。。。规律是重新排序,把大的依次往两边放,从最大的开始,第一个最左边,第二个最右边,依次往中间靠,放完了都算一下就是答案。需要注意的是根据他的条件可以判断出一层只能放一个球,这样很大程度上简化了问题。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn = 20;
double a[maxn],b[maxn];
bool cmp(double x,double y)
{
return x > y;
}
int main()
{
int n;
double R;
scanf("%d",&n);
if(n == 0)
{
printf("%.2f\n",0);
return 0;
}
for(int i = 0;i < n; ++i) scanf("%lf",&a[i]);
scanf("%lf",&R);
sort(a,a + n,cmp);
double ans = 0;
int l = 0,r = n - 1,cou = 0;
while(l <= r)
{
if(cou & 1) b[r--] = a[cou++];
else b[l++] = a[cou++];
}
ans = ans + b[0] + b[n - 1];
for(int i = 0;i < n - 1; ++i)
{
ans = ans +sqrt(4 * R * (b[i] + b[i + 1] - R));
}
printf("%.2f\n",ans);
return 0;
}