牛客——2018年全國多校演算法寒假訓練營練習比賽(第一場)
阿新 • • 發佈:2019-02-08
這場還是新生賽,主要是模擬,搜尋,遞推遞迴,思維題。模擬手速還是慢,也會考慮不周全。
G:搜尋:
程式碼:連結:https://www.nowcoder.com/acm/contest/67/G 來源:牛客網 題目描述 圈圈圓圓圈圈,lulu小朋友最近看喜羊羊看多了,老是受刺激就畫圓圈,聽到小於8的數字時,還會畫出十分有規律的圓圈,現在你需要根據樣例觀察出規律,編寫程式,根據輸入的數字n(n<8),輸出對應的圓圈。 輸入描述: 第一行是樣例數T(T<9) 第2到2+T-1行每行有一個整數n(n<8),代表lulu聽到的數字 輸出描述: 聽到對應數字時,輸出對應樣子的圓圈。 示例1 輸入 4 0 1 2 3 輸出 O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O O 說明 當n=0時輸出 O 當n=1時輸出 *O O*O *O 當n=2時輸出 ****O ***O*O ****O *O*****O O*O***O*O *O*****O ****O ***O*O ****O 上面的'O'是大寫英文字母O,'*'代表空格,每一行最後一個O後面不帶空格。 備註: 對於100%的資料, 0<T<9; 0<=n<8;
H:遞推遞迴#include<bits/stdc++.h> typedef long long LL; using namespace std; int len[8]={1,3,9,27,81,243,729,2187}; char a[2500][2500]; string s[2500]; void dfs(int i,int j,int n) { if(n==0) { a[i][j]='O'; // cout<<"i:"<<i<<" "<<"j"<<j<<endl; return; } dfs(i,j+len[n-1],n-1); dfs(i+len[n-1],j,n-1); dfs(i+len[n-1],j+2*len[n-1],n-1); dfs(i+2*len[n-1],j+len[n-1],n-1); } int main() { int t,n; int i,j,k; scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=0;i<len[n];i++){ s[i]=""; for(j=0;j<len[n];j++) a[i][j]=' '; } dfs(0,0,n); for(i=0;i<len[n];i++) { int cnt=len[n]-1; while(a[i][cnt]==' ') cnt--; for(j=0;j<=cnt;j++) s[i]+=a[i][j]; cout<<s[i]<<endl; } } return 0; }
這道題是大一時老師講過的原題。原諒我還是自己重推了一遍
連結:https://www.nowcoder.com/acm/contest/67/H 來源:牛客網 時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 32768K,其他語言65536K 64bit IO Format: %lld 題目描述 現在有一個大小n*1的收納盒,我們手裡有無數個大小為1*1和2*1的小方塊,我們需要用這些方塊填滿收納盒,請問我們有多少種不同的方法填滿這個收納盒 輸入描述: 第一行是樣例數T 第2到2+T-1行每行有一個整數n(n<=80),描述每個樣例中的n。 輸出描述: 對於每個樣例輸出對應的方法數 示例1 輸入 3 1 2 4 輸出 1 2 5 說明 n=4,有五種方法 1:1 1 1 1 2:2 1 1 3:1 2 1 4:1 1 2 5:2 2 備註: 對於100%的資料, 0 < T < 80; 0 < n <= 80。
程式碼:
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int n,t;
long long a[101];
long long b[101];
a[1]=1;
a[2]=2;
a[3]=3;
for(int i=4;i<=100;i++)
{
a[i]=a[i-1]+a[i-2];
}
while(~scanf("%d",&t))
{
for(int i=1;i<=t;i++)
{
cin>>b[i];
cout<<a[b[i]]<<endl;
}
}
}
三。暴力水題
連結:https://www.nowcoder.com/acm/contest/67/I
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
lulu喜歡小於等於1000的正整數,但是如果某個數是a或b的倍數,lulu會討厭這個數。如果某個數裡包含了a和b兩個數裡包含的數,lulu也會討厭。(例如a=14,b=23,如果數字中包含1、2、3、4這四個數中的任意一個數,lulu就會討厭這個數)。現在告訴你a,b,你能說出lulu喜歡的數有多少個麼。
輸入描述:
第一行是樣例數T
第2到2+T-1行每行有2個整數a b。
輸出描述:
輸出lulu喜歡的數的個數
示例1
輸入
3
2 3
14 23
1234 5678
輸出
171
190
7
說明
a=1234 b=5678的時候,只考慮含有數字9,0的數,只有7個,分別是9,99,999,90,990,909,900
備註:
對於100%的資料,
0 < T <= 20;
0 <= a <= 99999;
0 <= b <= 99999。
程式碼:
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[11];
int like;
void chai(int a,int b)
{
memset(num,0,sizeof(num));
while(a>0)
{
int hh=a%10;
num[hh]=1;
a=a/10;
}
while(b>0)
{
int hh=b%10;
num[hh]=1;
b=b/10;
}
}
int main()
{
//cout<<999%10<<endl;
int a,b;
int t;
while(~scanf("%d",&t))
{
for(int i=1;i<=t;i++)
{
cin>>a>>b;
like=0;
chai(a,b);
for(int i=0;i<=1000;i++)
{
if(i%a==0||i%b==0)
continue;
if(i>=1&&i<10)
{
if(num[i]==1)
continue;
}
else if(i>=10&&i<100)
{
if(num[i%10]==1||num[i/10]==1)
continue;
}
else if(i>=100&&i<1000)
{
if(num[i%10]==1)
continue;
if(num[i/100]==1)
continue;
if(num[(i/10)%10]==1)
continue;
}
else if(i==1000)
{
if(num[0]==1||num[1]==1)
continue;
}
//cout<<"i"<<i<<endl;
like++;
}
cout<<like<<endl;
}
}
return 0;
}
還有兩道模擬題,一直未過。。再模擬兩遍試試。A:吃雞
這道題就是很簡單的沒有思維的模擬。
題目:
連結:https://www.nowcoder.com/acm/contest/67/A
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
題目描述
在絕地求生(吃雞)遊戲裡,不同的槍支有不同的威力,更是可以搭配不同的配件,以提升槍支的效能。
每一把槍都有其威力及其可裝備配件種類。每一個配件有其所屬種類,可以為槍支提供威力的百分比加成。每一把槍只能裝備一個同類配件。給你n把槍支和m個配件,槍的威力為p,可裝備的配件數量為k,為k個不同型別的配件,同種類配件只可以裝備一個。配件種類用數字q表示,配件威力加成用一個小數b表示。請你挑選一把槍併為其搭配配件使其威力最大。
假設一把槍的威力是p,裝配的k個配件的威力加成是bi,那麼槍最後的威力w=p*(1+b1+b2+…+bk)。
輸入描述:
資料有多組,處理到檔案結束。
第一行兩個整數n和m,代表槍支數量和配件數量。
接下來n行,描述n把槍的屬性:第一個整數為p,代表槍支的威力;第二個整數為k,代表該槍支可裝備的配件數量;後面k個整數,代表可裝備配件的種類。
接下來m行,描述m個配件的屬性:第一個整數為q,代表配件的種類,第二個浮點數為b,代表配件可以為槍支提供的威力加成。
輸出描述:
每組資料輸出為一行,輸出一個浮點數,代表合理裝備配件後的槍支最大威力。精確到小數點後4位。
示例1
輸入
3 6
120 3 1 2 3
100 4 1 2 3 4
110 3 2 3 4
1 0.12
2 0.23
2 0.26
4 0.57
3 0.35
5 0.41
輸出
239.8000
說明
對於上面的樣例,正確答案應該是,使用第三把槍,配上第三、四、五個配件。
槍的最終威力就是110*(1+0.26+0.57+0.35)=239.8
備註:
對於100%的資料,
1 <= n,m,k,q <= 1000;
0 <= p <= 1000;
0 <= b <= 1。
我的程式碼:
#include<iostream>
#include<stdio.h>
using namespace std;
double shuchu[1010];
double xpp;
struct node
{
int p;
int k;
int zhonglei[1010];
}qiang[1010];
struct node1
{
// int p;
double b;
int logal;
}peijian[1010];
int main()
{
int n,m;
int p;
double b;
int num=0;
long double lala;
long double sum;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=1000;i++)
{
peijian[i].logal=0;
}
for(int i=1;i<=n;i++)
{
cin>>qiang[i].p>>qiang[i].k;
for(int j=1;j<=qiang[i].k;j++)
{
cin>>qiang[i].zhonglei[j];
}
}
for(int i=1;i<=m;i++)
{
cin>>p>>b;
if(peijian[p].logal==1)//表明這個配件之前有了
{
if(peijian[p].b<b)
peijian[p].b=b;
}
else
{
peijian[p].b=b;
peijian[p].logal=1;
}
}
xpp=0;
for(int i=1;i<=n;i++)
{
lala=1;
sum=qiang[i].p;
for(int j=1;j<=qiang[i].p;j++)
{
lala=lala+peijian[qiang[i].zhonglei[j]].b;
}
lala=lala*qiang[i].p;
// cout<<"lala:"<<lala<<endl;
if(lala>xpp)
xpp=lala;
}
// cout<<xpp<<endl;
printf("%.4lf\n",xpp);
}
return 0;
}
程式碼2:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k[1005],p[1005],q[1005][1005],a;
double b[1005],s,sum,ans;
int main()
{
while(cin>>n>>m)
{
ans=0;
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
cin>>p[i]>>k[i];
for(int j=1;j<=k[i];j++)
cin>>q[i][j];
}
for(int i=1;i<=m;i++)
{
cin>>a>>s;
b[a]=max(b[a],s);
}
for(int i=1;i<=n;i++)
{
s=1;
for(int j=1;j<=k[i];j++)
s+=b[q[i][j]];
sum=p[i]*s;
ans=max(ans,sum);
}
printf("%.4lf\n",ans);
}
}
值得學習的地方是,我用的struct進行槍與配對配件的配對,程式碼2直接用二維陣列表示,而且程式碼一太繁瑣,中間判斷最大的那個時寫的也很囉嗦。這也是我寫程式碼最應該改進的地方。F:吃雞——跑毒篇
這道題感覺就是要想透徹,一定要看樣例。將問題簡單化反而更好。
題目:
連結:https://www.nowcoder.com/acm/contest/67/F
來源:牛客網
題目描述
現在有一款很火的遊戲playerunknown's battlegrounds,人稱“吃雞”,在裡面經常面臨跑毒(從安全區外跑進安全區內)的問題,在安全區外,人們會處於中毒狀態,每秒會掉a%血,人們可以通過使用道具急救包把血量升回到80%,使用急救包需要原地站著6秒。現在知道在安全區外扣血速度為a%/s,角色和安全區的距離為b米,角色跑步速度為1m/s,角色有c個急救包,請問角色是否能安全跑進安全區內。(PS:角色開始的血量為100%。如果血量降到0%,立刻判定為死亡。使用急救包時,如果剛使用完畢瞬間或者正在使用急救包的時候,血量降到0%,角色立即判定為死亡。順帶一提,這裡判斷時間不存在0.xxxx秒,最小時間單位為1s)
輸入描述:
第一行是樣例數T(T<9)
第2到2+T-1行每行有三個整數a b c,其中a為安全區外的扣血速度a%/s,b為角色和安全區的距離,c為急救包的數量。
輸出描述:
如果角色能進入安全區輸出“YES”。
若角色在安全區外死亡輸出“NO”。
示例1
輸入
3
1 100 2
6 31 2
7 31 2
輸出
YES
YES
NO
說明
當a=6,b=31,c=2時,
0s起跑,10s的時候角色跑了10M,血量剩下40%,開始使用急救包,16s的時候,角色血量先降到4%再恢復到80%,然後角色繼續跑步。23s的時候,角色跑了17M,剩餘血量為38%,開始使用急救包,29s的時候,角色血量先降到2%再恢復到80%,然後角色繼續跑步。42s的時候,角色跑了30m,血量剩餘2%。當43s的時候,角色跑了31m進入了安全區內,不再扣血。
備註:
對於100%的資料,
1 <= T < 9;
0 < a <= 20;
0 < b <= 120;
0 <= c <= 8。
附上通過樣例為90.91%的程式碼以及大神的程式碼:
#include<stdio.h>
int main()
{
int t,a,b,c,hp;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&a,&b,&c);
hp=100;
while(b>1)
{
if(hp<=7*a&&c)
{
hp=80;
c--;
}
hp-=a;
b--;
}
if(hp>0)
printf("YES\n");
else
printf("NO\n");
}
}
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c,c22;
cin>>a>>b>>c;
c22=c;
int xueliang=100;
int time=0;
int jixian=6*a;
int logal=0;
int k=0;//表示用的急救包的次數
while(1)
{
if(b<=1)
break;
if(c==0)
{
if(c22!=0)
{
if(time+80/a>b-1)
logal==0;
else
logal=1;
break;
}
else if(c22==0)
{
if(time+100/a>b-1)
logal==0;
else
logal=1;
break;
}
}
xueliang=xueliang-a;
time++;//過了一秒鐘,走了1米
if(time>=b)
{
break;
}
if(xueliang-jixian<a)
{
c--;
if(c<0)
{
logal=1;
break;
}
xueliang=80;
continue;
}
}
if(logal==1)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
return 0;
}
程式碼簡潔是我要追求的。