1. 程式人生 > 實用技巧 >[Codeforces Round #677 (Div. 3)] G. Reducing Delivery Cost (dijkstra,列舉)

[Codeforces Round #677 (Div. 3)] G. Reducing Delivery Cost (dijkstra,列舉)

B - Power Sequence

題意:給n個數,可以把這n個數任意排列,把數列變成一個等比數列,使第i個數變成c的i次方。可以把任意一個數加一或者減一操作,每次此類操作都要花費 1,問最少花費是多少

題解:因為n>=3,ai<=109,所以公比最大為sqrt(1e9),取1e5使ai不大於1e9.列舉公比

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string
> using namespace std; #define max 100010 typedef long long ll; ll a[max]; int main(){ ll n,flag=0,minn=1e18; cin>>n; for(ll i=0;i<n;i++){ cin>>a[i]; } sort(a,a+n); for(ll q=1;q<=1e5;q++){ ll sum=0,m=1; bool flag=1; for(ll j=0;j<n;j++){
if(sum>minn){ flag=0; break; } sum+=abs(a[j]-m); m=m*q; } if(flag){ minn=min(minn,sum); }else{ break; } } cout<<minn<<endl; return 0; }
View Code

D - Drinks Choosing

題意:有n個學生和k種飲料,給出n個學生最想喝的飲料,能取 [ n/2 ]組飲料,每組含相同飲料兩杯,判斷最多有多少學生能喝到他們最喜歡的飲料

題解:如果能拿一組使兩杯飲料都有人喝肯定是最好的。把能湊成組的飲料放在sum1裡,如果多出來一杯就放在sum2裡,如果sum1裡的數量大於等於[ n/ 2]*2,那麼[ n/ 2]*2個人能喝到自己最喜歡的飲料;如果sum1的數量小於[ n/ 2]*2,那麼sum1+([ n/ 2]*2-sum1/2)能喝到自己最喜歡的飲料

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
int a[1010];
int main(){
    int n,k,x,temp,sum1=0,sum2=0,ans=0;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>x;
        a[x]++;
    }
    temp=(n+1)/2;
    for(int i=k;i>=1;i--){
        if(a[i]%2==0){
            sum1+=a[i];
        }else{
            sum1+=a[i]-1;
            sum2+=1;
        }
    }
    if(sum1>=temp*2){
        ans=temp*2;
    }else{
        ans=sum1+(temp-sum1/2);
    }
    cout<<ans<<endl;
    return 0;
}
View Code

E - Sport Mafia

題意:給n次動作和最後的糖果數k。在n次動作裡,你可以吃掉一顆或者在盒子裡放糖果(放的糖果會比之前多放1塊糖),使最後糖果數為k。如果盒子是空的只能在裡面放糖;求被吃掉的糖果數.

題解:假設在n次裡面有a次是放糖果,b次是吃糖果,則a+b=n;放入的糖果為(1+a)*a/2,吃掉的為b,即(1+a)*a/2+b=k 聯立兩個式子,求解(一開始沒看見放的糖果會比之前多放1塊糖,/(ㄒoㄒ)/~~)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
int main(){
    ll n,k,sum=0;
    cin>>n>>k;
    ll x=sqrt(2*n+2*k+2.25)-1.5;
    cout<<n-x<<endl;
    return 0;
}
View Code

F - Basketball Exercise

題意:有兩行身高數,每行n個,取過一個數之後,不能再取和它相鄰的數(不包括對角相鄰),問身高總和最大為多少

題解:可以先選擇第一行隊員,也可以選擇第二行隊員。要讓第i次的身高和最大,第i-1次的也應該最大,且第i次可以選擇也可以不選擇

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define MAX 100010
typedef long long ll;
ll a[MAX],b[MAX];
ll dp[2][MAX];
int main(){
    ll n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    for(int i=0;i<n;i++){
        cin>>b[i];
    }
    dp[0][0]=a[0];
    dp[1][0]=b[0];
    for(int i=1;i<n;i++){
        dp[0][i]=max(a[i]+dp[1][i-1],dp[0][i-1]);
        dp[1][i]=max(b[i]+dp[0][i-1],dp[1][i-1]);
    }
    ll end=max(dp[0][n-1],dp[1][n-1]);
    cout<<end<<endl;
    return 0; 
} 
View Code