12.18 20届第二次周测
b站题解:https://www.bilibili.com/video/BV1SK411u7aL
HDU 2002 计算球的体积
简单的基础运算,今日签到题。
#include<stdio.h>
#define PI 3.1415927
int main(){
double r;
while(~scanf("%lf",&r)){
printf("%.3lf\n",4*PI*r*r*r/3);
}
return 0;
}
HDU 2081 手机短号
考察对字符数组的一个使用。`
#include<stdio.h>
char a[15];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%s",&a);
printf("6");
for(int i=6;i<11;i++) printf("%c",a[i]);
printf("\n");
}
return 0;
}
HDU 2042 不容易系列之二
类似与本学期大一c语言考试中猴吃桃问题。
题中告诉到达市场时剩3只羊,且之前每经过一个站被拿走一半再还一只。
那么我们从后往前推 那就是 上一站的羊数=(当前羊数-1)*2
#include<stdio.h>
int main(){
int T;
scanf("%d",&T);
while(T--){
int a;
int res=3;
scanf("%d",&a);
while(a--){
res=(res-1)*2;
}
printf("%d\n",res);
}
return 0;
}
HDU 2092 整数解
我想到两种方法:
1.暴力枚举,从-9999枚举到9999。(由于数据范围较小,所以可暴力)
2.将两个方程联立成一个一元二次方程,使用根的判别式进行求解。
第一个方法比较好写,那就写第一个把。
#include <stdio.h>
int main(){
int s,m;
int i;
while(~scanf("%d%d",&s,&m)){
if(s==0 && m==0){
break;
}
for(i=-9999;i<=9999;i++){
if(i*(s-i)==m){
printf("Yes\n");
break;
}
}
if(i==10000){ //说明在上个for循环走走到尽头,没有被break,意味着无解
printf("No\n");
}
}
return 0;
}
HDU 2037 今年暑假不ac
考察了一个简单贪心问题。
再次科普下贪心是什么:在对问题求解时,总是作出在当前看来是最好的选择。也就是说,不从整体上加以考虑,它所作出的仅仅是在某种意义上的局部最优解(是否是全局最优,需要证明)。若要用贪心算法求解某问题的整体最优解,必须首先证明贪心思想在该问题的应用结果就是最优解
。
此题贪心思路为:我们讲所有节目按照结束时间排序,从小到大,那么我们再从头开始寻找下一个开始时间大于等于上一个结束时间。若满足则答案加一。循环操作。这样可获得这个问题的整体最优解。即看的最多完整节目数。
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int N=110;
typedef struct
{
int start; //节目开始时间
int end; //节目结束时间
}watch;//定义一个watch类型
watch p[N]; //一个watch类型 数组p
/*const int cmp( watch a, watch b)
{
return a.end<b.end;
}*/
int main()
{
int n;
while(scanf("%d",&n),n)
{
for(int i=0;i<n;i++) scanf("%d%d",&p[i].start,&p[i].end);
//sort(p,p+n,cmp); c++排序
for (int j = 0; j < n; j++) //适合现阶段大一的冒泡排序
{
for (int i = 0; i < n - 1 - j; i++)
if (p[i].end > p[i + 1].end) //以节目结束时间排序 从小到大
{
swap(p[i],p[i+1]);
}
}
int cnt=1;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
if(p[i].end<=p[j].start){ //寻找下一个开始时间大于等于上一个结束时间
i=j;
cnt++;
}
}
printf("%d\n",cnt);
}
return 0;
}
HDU 2046 骨牌铺方格
n 张牌可以由 n - 1 张牌后面再加一张竖着放的牌得到,还可以由 n - 2 张牌后面再加两张牌得到。
(n - 2 张牌后面再加两张牌的情况只能是加两张横着放的,如果加两张竖着放的牌会和“ n - 1 张牌后面再加一张牌”的情况重复。)
n规模的格子只能从n-1和n-2得来,n-1的时候我们增加一个2×1格子,竖着放,可以有s(n-1)种放法,n-2时候我们可以增加2×2个格子,2个都横着放,可以有s(n-2)种方法
综上所述,此题为斐波那契数列模型
#include <stdio.h>
int main()
{
int i, t;
while(~scanf("%d", &t))
{
long long int s[60]; //长整型 (可能会爆int)
s[0] = 1;
s[1] = 2;
for(i = 2; i < t; i++)
{
s[i] = s[i - 1] + s[i - 2];
}
printf("%lld\n",s[t - 1]);
}
return 0;
}
HDU 2050 折线割平面
该题为递推数学题;
图要自己去画,前面两条题目都已经给出了;
那么你把 n=3 的时候画出来就可以看到了,应该是被分成了16块;
n=4 的时候画出来可以看到,最多被分成了29块;
那么由 n=1 的时候分成了2块 ; n=2的时候分成了 7块 ,可以推出来:
f(2)-f(1)=5;
f(3)-f(2)=9;
9-5=4;
f(4)-f(3)=13;
13-9=4;
那么他们的加数的都是每次增加了 4;
可以推出 a(n)=5+4*(n-1); —> a(n)=4*n+1
所以可推出:f(n)=f(n-1)+4*(n-1)+1;
所以有递推公式:
f(n)=f(n-1)+4(n-1) + 1;
=f(n-2)+4(n-2)+4(n-1)+2;
.......
=f(n-(n-1)) +4(n-(n-1))+4(n-(n-2))+......+4(n-1) + n-1;
=f(1) +4(1+2+3+4+....+n-1)+n-1;
=2+4((n-1)(n-1+1)/2)+n-1;
=2n^2-n+1;
#include <stdio.h>
typedef long long LL;
int main()
{
int T,n;
LL r;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
r = 2*n*n - n + 1;
printf("%lld\n",r);
}
return 0;
}
HDU 2208 唉,可爱的小朋友
有m个小皮球和n个小朋友,小朋友是0~N-1号。
1.把每个小皮球看成一组,通过小皮球来进行递归遍历。
2.假设我们成功地把v号小朋友放进1号小皮球组,然后再进入一次dfs,把v+1号小朋友放进1号小皮球组,如果v+1号小朋友不能放进1号小皮球组,就把v+1号小朋友放进2号小皮球组,……,如果前面都失败了,就退回来,把v号小朋友放进2号小皮球组,直到如果找到了一个满足的方式,就返回true,否则如果所有情况都不成立,就返回false。
#include<stdio.h>
#include<string.h>
#define MAX 11
int n,m;
bool map[MAX][MAX];
int visited[MAX];//第i号小朋友进的组号
bool check(int v,int tag)//第v号小朋友想进第tag组
{
for(int i=0;i<n;i++)
if(i!=v&&visited[i]==tag&&map[v][i]==false)//i号小朋友玩tag号球,但是i号小朋友不喜欢v号小朋友
return false;
return true;
}
bool dfs(int v)
{
if(v>=n) //n个小朋友都有组了,递归结束,找到了可以找的答案
return true;
else
{
for(int i=1;i<=m;i++)//选择每个皮球作为分组
{
if(visited[v]==0&&check(v,i))//判断v号小朋友是否可以进i号皮球组
{
visited[v]=i;//加入第i组
if(dfs(v+1))//看看后面的小盆友可不可以成功
return true;
visited[v]=0;//没有成功,那么就不加入第i组
}
}
}
return false;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(map,false,sizeof(map));//false表示假设他们直接不喜欢一起玩
memset(visited,0,sizeof(visited));
int k,like;
for(int i=0;i<n;i++)
{
scanf("%d",&k);
for(int j=0;j<k;j++)
{
scanf("%d",&like);
map[i][like]=true;
map[like][i]=true;
}
}
if(m>=n)//球的数量大于等于小孩的数量,肯定可以玩
printf("YES\n");
else
{
if(dfs(0))
printf("YES\n");
else printf("NO\n");
}
}
}
总结:
后面的3道有点思维含量和推算能力,在你们现阶段水平是本场防AK的题目。没做出来也不用灰心。有问题可在下面评论。下周再接再厉,看好你们噢。