“科大訊飛杯”第十七屆同濟大學程序設計預選賽暨高校網絡友誼賽

A 張老師和菜哭武的遊戲
題目中有描述“當且僅當集合存在y和z,滿足x等於y+z或者y-z”
所以考慮y-z,很容易想到輾轉相減法,所以最小項是最大公約數
然後題目就迎刃而解了

#include <bits/stdc++.h>
using namespace std;
int n,a,b;
 
int gcd(int a,int b){
    if(a==b)return a;
    return a>b?gcd(a-b,b):gcd(b-a,a);
}
 
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n>>a>>b;
        int temp=gcd(a,b);
        int ans=n/temp;
        if(ans%2==1) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

B 傷害計算
看了題解,覺得還是用atoi更加簡單;
atoi主要用來將數字字符串轉變爲對應的整型數字,具體用法網上教程很多;
數學期望的計算公式是用各項權值乘以概率,常數的數學期望就是常數,公式推導還是挺簡單的;
注意題目中小數只有.5,所以方便計算,可以將各項結果先乘以2,最後除2,看餘數決定是否輸出.5;
ps:字符串題目多用函數可以減少很多時間;

#include <bits/stdc++.h>
using namespace std;
const int MAXL=6000;
char strfuc[MAXL];
int ans;

void opera(char *str){
    char *D=strchr(str,'d');
    if(D==NULL){
        int c=atoi(str);
        ans+=2*c;
        //cout<<c<<endl;
    }else{
        *D='\0';
        int n=atoi(str);
        int x=atoi(D+1);
        ans+=n*(x+1);
        //cout<<n<<" "<<x<<endl;
    }
}

int main(){
    while(cin>>strfuc){
        ans=0;
        char* str=strfuc;
        while(1){
            char* ps=strchr(str,'+');
            if(ps==NULL){
                opera(str);
                break;
            }else{
                *ps='\0';
                opera(str);
                str=ps+1;
            }
        }
        cout<<ans/2;
        if(ans%2) cout<<".5"<<endl;
        else cout<<endl;
    }
    return 0;
}

C 張老師的旅行
直覺上感覺可以用貪心去做;
結果wa了;
仔細想想還是不行,跟任務分配問題還是有區別的;
這道題dp還是比較難想的;
通俗的講:
比如你在起點位置,你左邊有i個景點,右邊有j個景點,問題就是問你瀏覽完所有景點的最小時間;
首先你不管以什麼順序瀏覽,你要麼最後停在i點,要麼最後停在j點;
所以要分兩種情況來討論;
以最後停在i點爲例;
這個問題的子問題,比如瀏覽完左邊的i-1個景點,右邊的j個景點的最短時間已經求得;
那麼對於子問題兩種情況的可行解(一種停在i-1點,一種停在j點),你都要回到i點,那麼加上對應的路程就可以了(想象你從i-1出發走到i,或從j出發走到i);
然後問題的解就是兩種情況的最小的那一個;
然後ac的代碼;

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f;
struct point{
    int deadline;
    int coordinate;
};
point mp[1100];
point leftpointSet[1100];
point rightpointSet[1100];
int dp[1100][1100][2];

bool cmp(point a,point b){
    return a.coordinate<b.coordinate;
}

int main(){
    int n;
    cin>>n;
    int my_coordinate;
    for(int i=1;i<=n;i++){
        cin>>mp[i].coordinate;
    }
    for(int i=1;i<=n;i++){
        cin>>mp[i].deadline;
        if(mp[i].deadline==0) my_coordinate=i;
    }
    sort(mp+1,mp+1+n,cmp);
    memset(dp,INF,sizeof(dp));
    dp[0][0][1]=0;
    dp[0][0][0]=0;
    int cnt_left=0,cnt_right=0;
    for(int i=my_coordinate-1;i>0;i--){
        cnt_left++;
        leftpointSet[cnt_left].coordinate=abs(mp[i].coordinate-mp[my_coordinate].coordinate);
        leftpointSet[cnt_left].deadline=mp[i].deadline;
    }
    for(int i=my_coordinate+1;i<=n;i++){
        cnt_right++;
        rightpointSet[cnt_right].coordinate=abs(mp[i].coordinate-mp[my_coordinate].coordinate);
        rightpointSet[cnt_right].deadline=mp[i].deadline;
    }
    /*
    cout<<my_coordinate<<endl;
    for(int i=1;i<=cnt_left;i++) cout<<leftpointSet[i].coordinate<<" ";
    cout<<endl;
    for(int j=1;j<=cnt_right;j++) cout<<rightpointSet[j].coordinate<<" ";
    cout<<endl;
    */
    for(int i=0;i<=cnt_left;i++){
        for(int j=0;j<=cnt_right;j++){
            if(i){
                dp[i][j][0]=min(dp[i-1][j][0]-leftpointSet[i-1].coordinate+leftpointSet[i].coordinate,dp[i-1][j][1]+rightpointSet[j].coordinate+leftpointSet[i].coordinate);
            }
            if(j){
                dp[i][j][1]=min(dp[i][j-1][1]-rightpointSet[j-1].coordinate+rightpointSet[j].coordinate,dp[i][j-1][0]+leftpointSet[i].coordinate+rightpointSet[j].coordinate);
            }
            if(dp[i][j][0]>leftpointSet[i].deadline && dp[i][j][1]>rightpointSet[j].deadline){
                cout<<-1<<endl;
                return 0;
            }
            if(dp[i][j][0]>leftpointSet[i].deadline) dp[i][j][0]=INF;
            if(dp[i][j][1]>rightpointSet[j].deadline) dp[i][j][1]=INF;

        }
    }
     cout<<min(dp[cnt_left][cnt_right][0],dp[cnt_left][cnt_right][1])<<endl;
     return 0;
}

D 車輛調度
注意車一次可以走到頭,同時不止一輛車,也不止一個終點;
這樣就要考慮車不僅會在遇到障礙物的情況下停下,也有可能在遇到車的時候停下,這時候僅僅把車的位置作爲bfs時的結點就不行了;
其實這種問題,非常像一種叫華容道的傳統遊戲;
因爲此時你上一步操作會影響下一步操作,這種情況下,一般可以將圖作爲bfs的結點,這樣每一個節點都是起點圖可能到達的一種情況,然後去找符合題目要求的圖就可以了;
因爲圖有可能重複,可以用一個set來去掉重複的圖(剪枝),同時因爲k已經給了,所以如果操作步驟超過了k,就可以輸出no,不需要再操作了;
ps:給出一道類似的題:Rush Hour Puzzle 有興趣可以做一下
代碼中的註釋去掉,可以瀏覽所有結點;
ac代碼:

#include <bits/stdc++.h>
#define P pair<int,int>
using namespace std;

int h,w;
int k;

struct mp{
    char p[15][15];
    bool friend operator<(const mp &a,const mp &b){
        for(int i=1;i<=h;i++){
            for(int j=1;j<=w;j++){
                if(a.p[i][j]!=b.p[i][j]) return a.p[i][j]<b.p[i][j];
            }
        }
        return false;
    }
};

struct node{
    P car[8];
    P goal[100];
    int cnt;
    mp p;
}c;

set <mp> st;
queue <node> q;
bool ans=false;

bool move(node &res,int id,int de){
    mp &p=res.p;
    P &car=res.car[id];
    int h1,w1;
    h1=car.first;
    w1=car.second;
    if(de==1){
        int temp=w;
        if(car.second==w) return false;
        for(int i=w1+1;i<=w;i++){
            if(p.p[h1][i]=='R' || p.p[h1][i]=='X'){
                temp=i-1;
                break;
            }
        }
        p.p[car.first][car.second]='.';
        car.first=h1;
        car.second=temp;
        p.p[car.first][car.second]='R';
    }
    if(de==2){
        int temp=1;
        if(car.second==1) return false;
        for(int i=w1-1;i>=1;i--){
            if(p.p[h1][i]=='R' || p.p[h1][i]=='X'){
                temp=i+1;
                break;
            }
        }
        p.p[car.first][car.second]='.';
        car.first=h1;
        car.second=temp;
        p.p[car.first][car.second]='R';
    }
    if(de==3){
        int temp=h;
        if(car.first==h) return false;
        for(int i=h1+1;i<=h;i++){
            if(p.p[i][w1]=='R' || p.p[i][w1]=='X'){
                temp=i-1;
                break;
            }
        }
        p.p[car.first][car.second]='.';
        car.first=temp;
        car.second=w1;
        p.p[car.first][car.second]='R';
    }
    if(de==4){
        int temp=1;
        if(car.first==1) return false;
        for(int i=h1-1;i>=1;i--){
            if(p.p[i][w1]=='R' || p.p[i][w1]=='X'){
                temp=i+1;
                break;
            }
        }
        p.p[car.first][car.second]='.';
        car.first=temp;
        car.second=w1;
        p.p[car.first][car.second]='R';
    }
    /*
    cout<<res.cnt<<endl;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            cout<<res.p.p[i][j]<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
    */
    return true;
}

int main(){
    int test;
    int cnt1=0;
    int cnt2=0;
    cin>>w>>h>>k;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            char m;
            cin>>m;
            if(m=='R') c.car[cnt1++]={i,j};
            if(m=='D') c.goal[cnt2++]={i,j};
            c.p.p[i][j]=m;
        }
    }
    st.insert(c.p);
    q.push(c);
    while(!q.empty()){
        c=q.front();
        q.pop();
        for(int i=0;i<cnt2;i++){
            int t1=c.goal[i].first;
            int t2=c.goal[i].second;
            if(c.p.p[t1][t2]=='R'){
                ans=true;
                test=c.cnt;
                break;
            }
        }
        if(ans) break;
        if(c.cnt>=k) continue;
        for(int i=0;i<cnt1;i++){
            for(int j=1;j<=4;j++){
                node res=c;
                res.cnt++;
                if(move(res,i,j)){
                    if(st.count(res.p)) continue;
                    else st.insert(res.p),q.push(res);
                }
            }
        }
    }
    if(ans) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章