目錄:
T1:移動奶牛
T2:電壓放大器
T3:步行
T4:數數
第一題USACO 後三題是市選……
正題:
T1:移動奶牛
題目描述
Farmer John的三頭獲獎奶牛Bessie、Elsie和Mildred,總是會迷路走到農場上遙遠的地方去!他需要你幫助將她們一起趕回來。
農場的草地大體是一塊狹長的區域——我們可以將其想象成一條數軸,奶牛可以佔據數軸上的任意整數位置。這3頭奶牛現在正位於不同的整數位置,Farmer John想要移動她們,使得她們佔據三個相鄰的位置(例如,位置6、7、8)。
不幸的是,奶牛們現在很困,Farmer John要讓她們集中精力聽從命令移動並不容易。任意時刻,他只能使得一頭處在“端點”(在所有奶牛中位置最小或最大)位置的奶牛移動。當他移動奶牛時,他可以命令她走到任意一個未被佔用的整數位置,只要在新的位置上她不再是一個端點。可以看到隨着時間的推移,這樣的移動可以使奶牛們趨向越來越近。
請求出使得奶牛們集中到相鄰位置所進行的移動次數的最小和最大可能值。
輸入
輸入包含一行,包括三個空格分隔的整數,爲Bessie、Elsie和Mildred的位置。每個位置均爲一個範圍1…10^9內的整數。
輸出
輸出的第一行包含Farmer John需要將奶牛們聚集起來所需進行的最小移動次數。第二行包含他將奶牛聚集起來能夠進行的最大移動次數。
樣例輸入
4 7 9
樣例輸出
1
2
分析:
大意就是
將位於數軸上的三個正整數點 通過若干次操作變成三個相鄰的點 每次操作只能將位於兩端的一個點置於另兩個點之間 求最少及最多次數
所以 模擬就好了
也可以找規律
CODE:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int a[100005],x=0;
int getmin(){ //找最小次數
if((a[3-2]-a[0]==3-2&&a[3-1]-a[3-2]>2)||(a[3-1]-a[1]==3-2&&a[1]-a[0]>2))
return 2;
int j=0;
for(int i=0;i<3;i++){
while(j<3-1&&a[j+1]-a[i]<=3-1)
j++;
x=max(x,j-i+1);
}
return 3-x;
}
int getmax(){
return max(a[3-2]-a[0],a[3-1]-a[1])-3+2; //最大次數
}
int main(){
freopen("herding.in","r",stdin);
freopen("herding.out","w",stdout);
for(int i=0;i<3;i++)
scanf("%d",&a[i]);
sort(a,a+3); //排序
printf("%d\n%d\n",getmin(),getmax());
return 0;
}
T2:電壓放大器
題目描述
西西需要把輸入的電壓1伏通過一系列電壓放大器放大成原來的N倍,然後輸出。
西西現在手上有兩種放大器:
第一種能夠把X伏的電壓放大成2X-1伏
第二種能夠把X伏的電壓放大成2X+1伏
放大器是串聯(即按順序放在一條線路上)的。
現在西西手上有用不完的放大器,他希望能組出一個電路,使用數量最少的放大器,使得電壓被放大了剛好N倍。
輸入
一行一個正整數N(1<=N<=2*10^9)
輸出
如果無法組成電路則輸出一行No solution
否則輸出兩行,第一行一個整數表示最少的放大器個數K,第二行K個用空格隔開的1或2,表示放大器序列。1表示第一種,2表示第二種,其中左邊爲輸入端。如果有多解輸出任意一組。
樣例輸入
5
樣例輸出
2
2 1
分析:
大意就是
給你一個1 讓你經過多次操作 分兩種:2x+1和2x−1 變爲n這個數 求最少要多少步 並輸出操作序號
分析奇偶性 你會發現無論如何得到的結果都是奇數 所以如果是偶數直接return 0
奆佬們提示說:
1 3 5 7 9 11 13 17 19……
+1 -1 +1 -1 +1 -1 +1 -1……
判斷項數 偶數就(x−1)/2否則就 (x+1)/2
CODE:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
long long n,m,ans[10010],i;
int main()
{
freopen("amp.in","r",stdin);
freopen("amp.out","w",stdout);
cin>>n;
if(n%2==0) //不存在
{
cout<<"No solution";
return 0;
}
else
{
while(n!=1)
{
i++,m=n/2;
if(m%2!=0) //判斷奇偶
n=m,ans[i]=2;
else
n=m+1,ans[i]=1;
}
}
cout<<i<<endl;
for(int j=i;j>=1;j--)
cout<<ans[j]<<" ";
return 0;
}
T3:步行
題目描述
ftiasch 又開發了一個奇怪的遊戲,這個遊戲是這樣的:有N 個格子排成一列,每個格子上有一個數字,第i 個格子的數字記爲Ai。這個遊戲有2 種操作:
-
如果現在在第i 個格子,則可以跳到第Ai 個格子。
-
把某個Ai 增加或減少1。
nm 開始在第1 個格子,他需要走到第N 個格子才能通關。現在他已經頭昏腦漲啦,需要你幫助他求出,從起點到終點最少需要多少次操作。
輸入
第1 行,1 個整數N。
第2 行,N 個整數Ai。
輸出
1 行,1 個整數,表示最少的操作次數。
樣例輸入
5
3 4 2 5 3
樣例輸出
3
分析:
BFS
a[i] 我們可以對 a[a[i]] a[a[i]−1] a[a[i]+1] 進行更新
CODE:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,i,j,a[100010],b[100010],c[100010],d[100010];
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
c[1]=1;
d[1]=d[a[1]]=1;
i=0,j=1;
while(i<j) //BFS
{
i++;
if(!d[a[b[i]]]) //以上三種情況
{
j++;
b[j]=a[b[i]];
c[j]=c[i]+1;
d[b[j]]=1;
if(b[j]==n)
{
printf("%d\n",c[j]);
return 0;
}
}
if(!d[b[i]-1])
{
j++;
b[j]=b[i]-1;
c[j]=c[i]+1;
d[b[j]]=1;
if(b[j]==n)
{
printf("%d\n",c[j]);
return 0;
}
}
if(!d[b[i]+1])
{
j++;
b[j]=b[i]+1;
c[j]=c[i]+1;
d[b[j]]=1;
if(b[j]==n)
{
printf("%d\n",c[j]);
return 0;
}
}
}
}
T4:數數
這道題幾個月前一次模擬賽做過了
寫過題解 是個三維DP
題解傳送門(第三題)