1. 程式人生 > >19.05.09 解題報告

19.05.09 解題報告

pop read 輸出 dig main long tdi int queue

預計得分:100+50+100=250
實際得分:5+50+0=55
發下試題,看了一遍三個題:
T1 題、裸的背包
T2 我可以模擬(

T3 **題、貪心、優先隊列

T1 多重背包

(backpack.cpp/c/pas)

(1s/256M)

題目描述

提供一個背包,它最多能負載重量為W的物品。
現在給出N種物品:對於第i類物品,一共有Ci件物品;對於每一件物品,重量為Wi,價值為Vi。
找出一種裝載方式使得背包中的物品總價值最大。

輸入格式(backpack.in)

第一行兩個整數N,W,代表物品的種類與背包的總負重。
第2~N+1行,每行三個整數Wi, Vi, Ci,代表第i種物品的重量、價值與數量。

輸出格式(backpack.out)

僅一行,一個整數V,代表最大的總價值。

樣例輸入

3 9
5 8 2
3 6 2
2 1 5

樣例輸出

14

數據範圍與限制

1<=N<=20, 0<=W<=1000
1<=Wi<=100, 0<=Vi<=100, 0<=Ci<=100

我是真的服我自己,好好的多重背包不寫,偏偏要逞能,寫個多重轉01背包,得個5分讓自己樂呵樂呵???(我是**嘛??)

AC代碼:

#include<iostream>
#include<cstdio>
using namespace std;

int N,W;

#define MAXN 1111

int w[MAXN],v[MAXN],c[MAXN];

inline int read() {
    int x=0,f=1;
    char c=getchar();
    for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
    for(;  isdigit(c); c=getchar()) x=x*10+c-'0';
    return x*f;
}

int f[MAXN];

int main() {
    freopen("backpack.in","r",stdin);
    freopen("backpack.out","w",stdout);
    cin>>N>>W;
    for(int i=1; i<=N; i++)
        cin>>w[i]>>v[i]>>c[i];
    for(int i=1; i<=N; i++)
        for(int j=1; j<=c[i]; j++)
            for(int k=W; k>=w[i]; k--)
                f[k]=max(f[k],f[k-w[i]]+v[i]);
    cout<<f[W];
    return 0;
}

T2 循環序列

(circulate.cpp/c/pas)

(1s/256M)

題目描述

Alice與Bob在玩遊戲:
Alice首先給出兩個數X與Y(X<=Y);
Bob則按順序將X,X+1,X+2,…,Y-1,Y寫成一個大數S。
Alice最後將S首尾相連,讓其圍成一個圈。
這時,Bob想知道,從S的開頭出發,往後的第L位到第R位數字之和是多少。

輸入格式(circulate.in)

第一行四個整數X,Y,L,R,代表Alice的兩個數字和Bob想要知道的第L位到第R位的數字之和。

輸出格式(circulate.out)

僅一行,一個整數M,代表第L位到第R位的數字之和。

樣例輸入

10 11 4 12

樣例輸出

7

樣例解釋

Bob將數字寫成一行大數S = 1011;圍成一個圈後,從第4位到第12位分別是1,1,0,1,1,1,0,1,1,它們的和是7.

數據範圍與限制

對於50%的數據,L=1, X,Y,L,R<=1000;
對於100%的數據,S的長度不大於10000,X,Y,L,R<=100000000.

考試的時候,蹦出來的第一個思路是**模擬(記錄+建環),看了眼數據範圍,覺得很騷,但是又沒有想到更好的,於是……

Code:(碼風鬼畜)

#include<iostream>
#include<cstdio>
using namespace std;

#define N 100000011

char S[N];

int X,Y,L,R;

inline int read() {
    int x=0,f=1;
    char c=getchar();
    for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;
    for(;  isdigit(c); c=getchar()) x=x*10+c-'0';
    return x*f;
}

int cnt=0;

int ans=0;

int main(void) {
    freopen("circulate.in","r",stdin);
    freopen("circulate.out","w",stdout);
    X=read();
    Y=read();
    L=read();
    R=read();
    for(int i=X; i<=Y; i++) {
        if((i/10)==0) {
            S[cnt++]=(char)i;
        } else if((i/10<10) && (i/10>0)) {
            S[cnt++]=(char)(i/10);
            S[cnt++]=(char)(i%10);
        } else if((i/100<10) && (i/100>0)) {
            S[cnt++]=(char)(i/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/1000<10) && (i/1000>0)) {
            S[cnt++]=(char)(i/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/10000<10) && (i/10000>0)) {
            S[cnt++]=(char)(i/10000);
            S[cnt++]=(char)(i%10000/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/100000<10) && (i/100000>0)) {
            S[cnt++]=(char)(i/100000);
            S[cnt++]=(char)(i%100000/10000);
            S[cnt++]=(char)(i%10000/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/1000000<10) && (i/1000000>0)) {
            S[cnt++]=(char)(i/1000000);
            S[cnt++]=(char)(i%1000000/100000);
            S[cnt++]=(char)(i%100000/10000);
            S[cnt++]=(char)(i%10000/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/10000000<10) && (i/10000000>0)) {
            S[cnt++]=(char)(i/10000000);
            S[cnt++]=(char)(i%10000000/1000000);
            S[cnt++]=(char)(i%1000000/100000);
            S[cnt++]=(char)(i%100000/10000);
            S[cnt++]=(char)(i%10000/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        } else if((i/100000000<10) && (i/100000000>0)) {
            S[cnt++]=(char)(i/100000000);
            S[cnt++]=(char)(i%100000000/10000000);
            S[cnt++]=(char)(i%10000000/1000000);
            S[cnt++]=(char)(i%1000000/100000);
            S[cnt++]=(char)(i%100000/10000);
            S[cnt++]=(char)(i%10000/1000);
            S[cnt++]=(char)(i%1000/100);
            S[cnt++]=(char)(i%100/10);
            S[cnt++]=(char)(i%10);
        }
    }
    int opt=cnt-1;
    for(int i=0; i<cnt; i++) {
        S[++opt]=S[i];
    }//2
    for(int i=0; i<2*cnt; i++) {
        S[++opt]=S[i];
    }//4
    for(int i=0; i<4*cnt; i++) {
        S[++opt]=S[i];
    }//8
    for(int i=0; i<8*cnt; i++) {
        S[++opt]=S[i];
    }//16
    for(int i=0; i<16*cnt; i++) {
        S[++opt]=S[i];
    }//32
    for(int i=0; i<32*cnt; i++) {
        S[++opt]=S[i];
    }//64
    for(int i=0; i<64*cnt; i++) {
        S[++opt]=S[i];
    }//128
    for(int i=0; i<128*cnt; i++) {
        S[++opt]=S[i];
    }//256
    for(int i=0; i<256*cnt; i++) {
        S[++opt]=S[i];
    }//512
    for(int i=0; i<512*cnt; i++) {
        S[++opt]=S[i];
    }//1024
    for(int i=L-1; i<R; i++) {
        ans+=(int)S[i];
    }
    cout<<ans;
    /*  for(int i=2*opt;i>=opt+1;i--){
            S[i]=
        }*/
    /*  for(int i=1; i<=cnt; i++)
            cout<<(int)S[i]<<"\n";*/
    return 0;
}

不過考試的時候,看見坐在我旁邊的cgp Dalao一直在咳咳(面露微笑)。闊怕闊怕~隱隱約約還聽到他忽然叫了一句:我想到優化了!!(果然,我太菜了)

AC代碼:

#include<iostream>
#include<stack>
#include<cstdio>
#include<cstring>

using namespace std;

#define N 100011

#define LL long long int

stack<int>S;

int a[N];

int cnt=0;

LL x,y,l,r,k;

LL ans=0,sum=0;

int main(void) {
    freopen("circulate.in","r",stdin);
    freopen("circulate.out","w",stdout);
    cin>>x>>y>>l>>r;
    while(x<=y) {
        k=x;
        while(k!=0) {
            S.push(k%10);
            k=k/10;
        }
        while(!S.empty()) {
            cnt++;
            a[cnt]=S.top();
            S.pop();
        }
        x++;
    }
    int flag=0;
    sum=1;
    for(int i=1; i<=cnt+1; i++) {
        if(i==cnt+1) i=1;
        if(sum==l) {
            flag=1;
        }
        if(flag)
            ans+=a[i];
        sum++;
        if(sum==r+1) break;
    }
    cout<<ans;
    return 0;
}

T3合並遊戲

merge.cpp/c/pas

(1s/256M)

題目描述

Cindy和Dan在玩一個遊戲。
一開始Cindy想出了N個數,接著她把這N個數全部給了Dan。

Dan得到這組數後,它會挑出3個數(如果不足3個則全部挑出)。Dan會把這幾個數加起來變成一個數,然後再把這個數與剩下的數再放到一起。Dan會一直這樣做,直到最後只剩下一個數。

Cindy則會在旁邊記下每次Dan得到的數,她把這些數加起來,作為本次遊戲的得分。她想知道,對於一組數,Dan能得到的最大的得分是多少?

輸入格式

第一行一個正整數N,代表這組數的個數;
第二行N個正整數,代表這N個整數。

輸出格式

一行一個整數,代表可能的最大得分。

樣例輸入(merge.in)

4
3 1 5 6

樣例輸出(merge.out)

29

樣例解釋

Dan可以首先把(3,5,6)這三個數先合並起來,得到3 + 5 +6 = 14;接著他把剩下的兩個數再合起來,得到1+14=15.這樣,總得分是最大的 14 + 15 = 29.

數據範圍與限制

對於50%的數據,N<=10
對於100%的數據,N<=1000,所有數不大於1000

快讀毀所有

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1111

int n;

int a[N];

int ans=0;

int opt=0;

int main(void) {
    freopen("merge.in","r",stdin);  
    freopen("merge.out","w",stdout);    
    priority_queue<int> Q;//大頭堆
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>a[i];
        Q.push(a[i]);
    }
    if(n<=3) {
        for(int i=1; i<=n; i++) ans+=a[i];
        cout<<ans;
        return 0;
    } else {
        ans+=Q.top();
        Q.pop();//1
        ans+=Q.top();
        Q.pop();//2
        ans+=Q.top();
        Q.pop();//3
        Q.push(ans);
        int uxv=0;
        while(Q.size()>3) {
            for(int i=1; i<=3; i++) {
                uxv+=Q.top();
                Q.pop();
            }
            ans+=uxv;
            Q.push(uxv);
            uxv=0;
        }
        uxv=0;
        if(Q.size()<=3) {
            while(!Q.empty()) {
                uxv+=Q.top();
                Q.pop();
            }
            ans+=uxv;
        }
        cout<<ans;
        return 0;
    }
}
綜合而言:這次考試我真的**了。

19.05.09 解題報告