1. 程式人生 > >2017-10-7 清北刷題沖刺班a.m

2017-10-7 清北刷題沖刺班a.m

同時 .cpp play 很多 註意 names 出現的次數 char fin

測試


A 消失的數字


文件名 輸入文件 輸出文件 時間限制 空間限制
del.cpp/c/pas del.in del.out 1s 512MB
題目描述
現在,我的手上有 n 個數字,分別是 a 1 ,a 2 ,a 3 ,...,a n 。
我現在需要刪除其中的 k 個數字。當然我不希望隨隨便便刪除,我希望刪除 k
個數字之後,剩下的 n − k 個數中有最多的不同的數。
輸入格式
第一行兩個正整數 n 和 k,含義如題目描述。
接下來一行,有 n 個非負整數,分別是 a 1 到 a n 。
輸出格式
一共一行,一個整數 ans,表示刪除了 k 個數字後最多的不同的數的個數。
樣例輸入
4 1
1 3 1 2

樣例輸出
3
樣例解釋
如果刪去第一個 1:
在[3,1,2]中有 3 個不同的數
如果刪去 3:
在[1,1,2]中有 2 個不同的數
如果刪去第二個 1:
在[1,3,2]中有 3 個不同的數
如果刪去 2:
在[1,3,1]中有 1 個不同的數
數據範圍
對於 30% 的數據,n ≤ 10,a i ≤ 10。
對於 60% 的數據,n ≤ 100,a i ≤ 100。
對於 80% 的數據,n ≤ 10 5 ,a i ≤ 10 5 。
對於 100% 的數據,n ≤ 10 5 ,a i ≤ 10 9 。

技術分享
#include<iostream>
#include<cstdio>
#include
<algorithm> #define maxn 100010 using namespace std; int n,a[maxn],k,cnt; int main(){ freopen("del.in","r",stdin);freopen("del.out","w",stdout); //freopen("Cola.txt","r",stdin); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++)scanf("%d",&a[i]); sort(a+1,a+n+1);
for(int i=1;i<=n;i++) if(a[i]!=a[i-1])cnt++; k-=n-cnt; if(k>=0)cnt-=k; printf("%d",cnt); fclose(stdin);fclose(stdout); return 0; }
100分


B 國際跳棋


文件名 輸入文件 輸出文件 時間限制 空間限制
chess.cpp/c/pas chess.in chess.out 1s 512MB
題目描述
國際跳棋是一種古老的棋類遊戲,遠在古埃及法老時期就已存在,現代國際跳
棋是在 12 世紀定型的。國際跳棋是由各國的民族跳棋演變而來,其歷史源遠流長。
簡化版(與標準國際跳棋略有差別)國際跳棋規則:
• 國際跳棋的棋盤由 10 × 10 共 100 個格子組成
• 初始的時候,黑白雙方各有 20 個棋子
• 移動:可以將我方任意棋子向左前方或右前方移動 1 步
• 跳吃:只要左前方、右前方、左後方、右後方相鄰格子有對方棋子,且跳過這
枚對方棋子後有空位,則可以跳過對方棋子並將對方棋子吃掉。如你的棋子在
(x,y), 對方棋子在 (x+1,y+1), (x+2,y+2) 為空, 則你可以跳到 (x+2,y+2)
並吃掉對方的棋子
• 加冕: 任何一個棋子在行動過程停止的時候停到了對方底線(最靠近對方的一
行)就可以加冕,從此成為“王”。註意,連續跳吃的時候只有最後一步停在對
方底線才可以加冕
• 連跳:跳吃可以由多次跳吃組成。
• 王的特權:王在移動的時候可以無視方向(左前、右前、左後、右後都可以) ,
無視距離(走幾步都行, 直到遇到別的棋子) , 無視跳吃距離(比如說 (x,y) 跳
過 (x + 3,y + 3) 落到 (x + 7,y + 7) 是可以的,但是這中間除了有被吃掉的對
方棋子,不能有其他棋子
• 在跳吃結束的時候才將被吃掉的棋子拿出棋盤,在這之前作為“屏障”,即這些
棋子不能再次被跳吃,也不能落子
• 按照以上規則,給定一個棋局,合法的操作方案有很多。然而,每次必須選擇
吃子最多的操作方案。比如,在某種棋局下,有 A、B、C、D 四種方案,A、
B 吃子 3 枚,C 吃 1 枚,D 吃 0 枚,則真正合法的操作總數為 2
作為一個國際跳棋迷,陶陶想要編寫一個網絡對戰跳棋軟件。然而他現在不會
判斷怎樣的操作是合法的。對於給定的局面,你能給出所有合法的操作嗎?
輸入格式
輸入數據是兩個十行十列的矩陣,第一個矩陣中的每個點可能是以下三種:
• 0 空位置
• 1 我方棋子
• 2 對方棋子
第二個矩陣描述的是國王的情況。若為 1,表示是國王;為 0 表示不是國王。
輸出格式
輸出第一行為一個數字,表示合法操作的個數 ans。
下面一共 ans 行,每行表示一種合法操作中被操作的棋子。格式為 (x,y) 表示
該棋子在第 x 行、第 y 列(註意,逗號後面沒有空格) 。如果某一個棋子有多種合
法操作,則輸出多遍。輸出的順序按從上到下、從左到右。
如果沒有任何合法操作,只輸出一個 0 即可
樣例輸入 1
0000000000
0000100000
0000000200
0000100000
0000000200
0000001000
0000000200
2000000000
0101000200
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
樣例輸出 1
2
(6,7)
(6,7)

技術分享
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
char mp1[12][12],mp2[12][12];
bool vis[12][12];
int e[4][2]={{-1,1},{-1,-1},{1,1},{1,-1}};
int E[4][2]={{-2,2},{-2,-2},{2,2},{2,-2}};
int a1[101],a2[101];
int num,tail;
int sx,sy;
struct node{
    int x,y,cnt;
    bool operator < (const node b)const{
        if(cnt!=b.cnt)return cnt>b.cnt;
        if(x!=b.x)return x<b.x;
        return y<b.y;
    }
}q[500000];
node Node(int x,int y,int cnt){
    node w;
    w.x=x;w.y=y;w.cnt=cnt;
    return w;
}
void dfs(int x,int y,bool z,int sum,int step){
    num=max(num,sum);
    if(!z){
        bool flag=0;
        for(int i=0;i<4;i++){
            int xx=x+e[i][0],yy=y+e[i][1];
            int xxx=x+E[i][0],yyy=y+E[i][1];
            if(xx<=10&&xx>=1&&yy<=10&&yy>=1&&mp1[xx][yy]==2&&!vis[xx][yy]&&(mp1[xxx][yyy]==0||(xxx==sx&&yyy==sy))){
                flag=1;
                vis[xx][yy]=1;
                dfs(xxx,yyy,z,sum+1,step+1);
                vis[xx][yy]=0;
            }
        }
        if(!flag){
            if(sum==num&&step){
                q[++tail]=Node(sx,sy,sum);
            }
        }
    }
    else{
        bool flag=0;
        for(int i=0;i<4;i++){
            int xx=x+e[i][0],yy=y+e[i][1];
            int xxx=xx+e[i][0],yyy=yy+e[i][0];
            while(1){
                if(xx<=10&&xx>=1&&yy<=10&&yy>=1&&mp1[xx][yy]==2&&!vis[xx][yy]&&mp1[xxx][yyy]==0)
                flag=1,dfs(xx,yy,z,sum+1,step+1);
                if(xx>10||xx<1||yy>10||yy<1||mp1[xx][yy]!=0)break;
                flag=1,dfs(xx,yy,z,sum,step+1);
                xx=xx+e[i][0];yy=yy+e[i][0];
                xxx=xx+e[i][0],yyy=yy+e[i][0];
            }
        }
        if(!flag){
            if(sum==num){
                q[++tail]=Node(sx,sy,sum);
            }
        }
    }
}
int main(){
    freopen("chess.in","r",stdin);freopen("chess.out","w",stdout);
    //freopen("Cola.txt","r",stdin);
    for(int i=1;i<=10;i++)scanf("%s",mp1[i]+1);
    for(int i=1;i<=10;i++)scanf("%s",mp2[i]+1);
    for(sx=1;sx<=10;sx++){
        for(sy=1;sy<=10;sy++){
            if(mp1[sx][sy]==1){
                num=0;
                if(mp2[sx][sy]==1){
                    dfs(sx,sy,1,0,0);
                }
                else {
                    for(int k=0;k<2;k++){
                        int xx=sx+e[k][0],yy=sy+e[k][1];
                        if(xx<=10&&xx>=1&&yy<=10&&yy>=1&&mp1[xx][yy]==0){
                            q[++tail]=Node(sx,sy,0);
                        }
                    }
                    dfs(sx,sy,0,0,0);
                }
            }
        }
    }
    if(tail==0){
        printf("0\n");
        return 0;
    }
    sort(q+1,q+tail+1);
    //for(int i=1;i<=tail;i++)cout<<q[i].x<<‘ ‘<<q[i].y<<‘ ‘<<q[i].cnt<<endl;
    int limit=q[1].cnt,top=1;
    int ans=0,t=0;
    while(1){
        if(q[top].cnt!=limit||top>tail)break;
        ans++;
        a1[++t]=q[top].x;a2[t]=q[top].y;
        top++;
    }
    printf("%d\n",ans);
    for(int i=1;i<=t;i++){
        printf("(%d,%d)\n",a1[i],a2[i]);
    }
    fclose(stdin);fclose(stdout);
    return 0;
}
60分 模擬


C 天上掉餡餅


文件名 輸入文件 輸出文件 時間限制 空間限制
bonus.pas/c/cpp bonus.in bonus.out 1s 128MB
題目描述
小 G 進入了一個神奇的世界,在這個世界,天上會掉下一些餡餅。今天,天上
會隨機掉下 k 個餡餅。
每次天上掉下餡餅, 小 G 可以選擇吃或者不吃(必須在下一個餡餅掉下來之前
作出選擇,並且現在決定不吃的話以後也不能吃) 。
餡餅有 n 種不同的餡,根據物理定律,天上掉下這 n 種餡餅的概率相同且相互
獨立。然而,每一種餡餅 i 都有一個前提餡餅集合 S i 。只有當 S i 中的餡餅都吃過
之後,才能吃第 i 種餡餅。比如說,韭菜餡餡餅的 S 中有白菜豬肉餡餅和鮮蝦餡餅,
那麽小 G 只有在吃過白菜豬肉餡餅和鮮蝦餡餅之後,才能吃韭菜餡的餡餅。
同時,每個餡餅還有一個美味值 P i 。今天一天小 G 的幸福度,等於小 G 吃到
的所有餡餅的美味值之和。註意,P i 可能是負數。
現在考慮,在采用最優策略的前提下,小 G 這一天期望的幸福度是多少?
輸入格式
第一行兩個正整數 k 和 n,表示餡餅的數量和種類。
以下 n 行,每行若幹個數,描述一種餡餅。其中第一個數代表美味值,隨後的
整數表示該餡餅的前提餡餅,以 0 結尾。
輸出格式
輸出一個實數,保留 6 位小數,即在最優策略下期望的幸福度。
樣例輸入 1
1 2
1 0
2 0
樣例輸出 1
1.500000
數據範圍
對於 20% 的數據,所有的餡餅都沒有“前提餡餅”
對於 50% 的數據,1 ≤ k ≤ 10,1 ≤ n ≤ 10
對於 100% 的數據,1 ≤ k ≤ 100,1 ≤ n ≤ 15,美味度為屬於 [−10 6 ,10 6 ] 的整

技術分享
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 20
using namespace std;
int k,n,w[maxn],p[maxn][maxn];
long long Pow(long long a,long long b){
    long long res=1;
    while(b){
        if(b&1)res=res*a;
        a=a*a;
        b>>=1;
    }
    return res;
}
int main(){
    freopen("bonus.in","r",stdin);freopen("bonus.out","w",stdout);
    scanf("%d%d",&k,&n);
    int x;
    for(int i=1;i<=n;i++){
        scanf("%d",&w[i]);
        while(1){
            scanf("%d",&x);
            if(x==0)break;
            p[i][++p[i][0]]=x;
        }
    }
    bool flag=1;//是否都沒有前提餡餅 
    for(int i=1;i<=n;i++){
        if(p[i][0]){
            flag=0;
            break;
        }
    }
    if(flag){
        long long ti=1LL*Pow(n,k-1)*k;//每種餡餅出現的次數 
        long long vir=Pow(n,k);
        long long ans=0;
        for(int i=1;i<=n;i++){
            ans=ans+1LL*ti*w[i];
        }
        long double now=(long double)ans/(long double)vir;
        double Ans=now;
        printf("%.6lf",Ans);
        return 0;
    }
    printf("2.333333");
    return 0;
}
10分 特判

2017-10-7 清北刷題沖刺班a.m