2012 Multi-University Training Contest 1

HDU-4301 Divide Chocolate(dp)

题意:给一个2*n的巧克力,把他分成k块,问有几种分法。(n<=1000)

题解:dp,状态比较多,dp[i][j][k]表示前i列分成了j块,k=0表示第i列上下相连,k=1表示第i列上下分开,的种类数

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 100000007

using namespace std;

int dp[1010][1010*2][2];
int n, k;

int main(){
    int T;
    memset(dp, 0, sizeof(dp));
    dp[1][2][1] = 1;
    dp[1][1][0] = 1;

    for(int i = 2; i<=1000; i++){
        for(int j = 1; j<=2*i; j++){
            dp[i][j][0] = (dp[i-1][j][0]+dp[i-1][j][1]*2+dp[i-1][j-1][0]+dp[i-1][j-1][1])%mod;
            dp[i][j][1] = (dp[i-1][j][1]+dp[i-1][j-1][1]*2+dp[i-1][j-1][0]*2)%mod;
            if(j>=2) dp[i][j][1] = (dp[i][j][1]+dp[i-1][j-2][1]+dp[i-1][j-2][0])%mod;
        }
    }
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &n, &k);
        printf("%d\n", (dp[n][k][0]+dp[n][k][1])%mod);
    }

    return 0;
}

HDU-4302 Holedox Eating(树状数组+二分)

题意:在一个序列上有两种操作,0 x 表示在x这个位置加一块事物,1 表示Holedox要吃掉离他最近的一块事物,如果最近的有两种选择,则他选择前进方向是原方向的那一块事物。

题解:用树状数组+二分可以求出当前位置右边和左边第一个大于0的元素的位置

代码:

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

using namespace std;


int c[100010*4];
int L, n;

int lowbit(int x){
    return x&(-x);
}

void update(int i, int x){
    while(i<=100010){
        c[i] = c[i]+x;
        i += lowbit(i);
    }
}

int sum(int x){
    int sum = 0;
    while(x>0){
        sum += c[x];
        x -= lowbit(x);
    }
    return sum;
}

int main(){
    int T;
    scanf("%d", &T);
    for(int t = 1; t<=T; t++){
        memset(c, 0, sizeof(c));
        int now = 1;
        int flag = 1;
        int dis = 0;
        scanf("%d%d", &L, &n);
        L++;
        //update(1, 1);
        //cout<<sum(1)-sum(0)<<endl;
        while(n--){
            int ch, x;
            scanf("%d", &ch);
            if(ch == 0){
                scanf("%d", &x);
                x++;
                update(x, 1);
            }
            else{
                if(sum(now)-sum(now-1)>0){
                    //cout<<"! "<<now<<endl;
                    update(now, -1);
                    //cout<<"asd"<<endl;
                    continue;
                }
                else if(sum(L)-sum(now) == 0 && sum(now-1)-sum(0) == 0){
                   // cout<<"! "<<sum(L)<<endl;
                    //cout<<"gg"<<endl;
                    continue;
                }
                else{
                    int l = now+1, r = L;
                    int temp1 = 0x3f3f3f3f;
                    while(l<=r){
                        int mid = (l+r)>>1;
                        if(sum(mid)-sum(now)>=1){
                            temp1 = mid;
                            r = mid-1;
                        }
                        else{
                            l = mid+1;
                        }
                    }


                    l = 1; r = now-1;
                    int temp2 = 0;
                    while(l<=r){
                        int mid = (l+r)>>1;
                        if(sum(now-1)-sum(mid-1)>=1){
                            temp2 = mid;
                            l = mid+1;
                        }
                        else{
                            r = mid-1;
                        }
                    }
                    //cout<<now<<" "<<temp1<<" "<<temp2<<endl;
                    if(temp1 == 0x3f3f3f3f){
                        dis+=now-temp2;
                        now = temp2;
                        flag = 0;
                        update(now, -1);
                        continue;
                    }
                    if(temp2 == 0){
                        dis+=temp1-now;
                        now = temp1;
                        flag = 1;
                        update(now, -1);
                        continue;
                    }

                    if(now-temp2 == temp1-now){
                        if(flag == 1){
                            dis+=temp1-now;
                            now = temp1;
                            update(now, -1);
                        }
                        else{
                            dis+=now-temp2;
                            now = temp2;
                            update(now, -1);
                        }
                    }
                    else if(now-temp2>temp1-now){
                        dis+=temp1-now;
                        now = temp1;
                        flag = 1;
                        update(now, -1);
                    }
                    else if(now-temp2<temp1-now){
                        dis+=now-temp2;
                        now = temp2;
                        flag = 0;
                        update(now, -1);
                    }

                }
            }
            //cout<<" "<<dis<<endl;
        }
        printf("Case %d: %d\n", t, dis);
    }

    return 0;
}

HDU-4308 Saving Princess claire_(简单bfs)

题意:从Y走到C,#表示障碍,*表示要花费c时间,从一个P可以通道任意一个P,求最短花费时间

题解:碰到第一个P就把所有P入队

代码:



#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

int n, m, c;
char ma[5010][5010];
bool vis[5010][5010];
int yx, yy, cx, cy;
int cnt;

int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};

struct node{
    int x, y;
    int dis;
}p[5010];

void solve(){
    memset(vis, false, sizeof(vis));
    queue<node> que;
    while(que.size()) que.pop();
    node q;
    q.x = yx; q.y = yy; q.dis = 0;
    vis[q.x][q.y] = true;
    que.push(q);

    while(que.size()){
        node f = que.front();
        que.pop();

        if(f.x == cx && f.y == cy){
            printf("%d\n", f.dis);
            return;
        }

        for(int i = 0; i<4; i++){
            int fx = f.x+dx[i];
            int fy = f.y+dy[i];
            if(fx>=1 && fx<=n && fy>=1 && fy<=m && ma[fx][fy]!='#' && vis[fx][fy] == false){
                if(ma[fx][fy] == 'P'){
                    for(int j = 0; j<cnt; j++){
                        q.x = p[j].x; q.y = p[j].y; q.dis = f.dis;
                        vis[q.x][q.y] = 1;
                        que.push(q);
                    }
                }

                if(ma[fx][fy] == '*'){
                    q.x = fx; q.y = fy; q.dis = f.dis+c;
                    vis[q.x][q.y] = 1;
                    que.push(q);
                }
                if(ma[fx][fy] == 'C'){
                    printf("%d\n", f.dis);
                    return;
                }
            }
        }

    }
    printf("Damn teoy!\n");
}



int main(){
    while(scanf("%d %d %d", &n, &m, &c) != EOF){
        cnt = 0;
        for(int i = 1; i<=n; i++){
            scanf("%s", ma[i]+1);
        }
        for(int i = 1; i<=n; i++){
            for(int j = 1; j<=m; j++){
                if(ma[i][j] == 'Y'){
                    yx = i; yy = j;
                }
                if(ma[i][j] == 'C'){
                    cx = i; cy = j;
                }
                if(ma[i][j] == 'P'){
                    p[cnt].x = i; p[cnt++].y = j;
                }
            }
        }
        solve();

    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值