2014-2015 ACM-ICPC Northeastern European Regional Contest (NEERC 14)

28 篇文章 0 订阅
24 篇文章 0 订阅

此处有目录↑


题目链接:http://codeforces.com/gym/100553


Problem A. Alter Board


题目大意:给定一个n*m的棋盘,棋盘有黑白两种颜色,且任意相邻的两个格子中的颜色不一样,每次可以选一个矩形,使其中每个格子的颜色换成另一种颜色,求最少几步能将棋盘变成一种颜色,并输出方案。

每次只对偶数行和偶数列转换,则答案最小

#include <cstdio>
#include <cstring>

using namespace std;

int n,m;

int main() {
    freopen("alter.in","r",stdin);
    freopen("alter.out","w",stdout);
    while(2==scanf("%d%d",&n,&m)) {
        printf("%d\n",n/2+m/2);
        for(int i=2;i<=n;i+=2) {
            printf("%d %d %d %d\n",i,1,i,m);
        }
        for(int j=2;j<=m;j+=2) {
            printf("%d %d %d %d\n",1,j,n,j);
        }
    }
    return 0;
}

Problem B. Burrito King (贪心)



题目大意:一个煎饼可由n种原料组成,第i种原料由3个数描述:g[i]、a[i] 和 b[i],表示第i种原料不能超过g克,要求确定每种原料的数量s[i],使得∑s[i]*a[i]>=A,且∑s[i]*b[i]<=B,若存在多种情况,则要求∑s[i]*a[i]最大。

要答案最优,则定有 ∑s[i]*b[i]==B 或者 ∑g[i]*b[i]<=B,由于可以去实数克,所以每次必定取a[i]/b[i]最大的,所以排序后贪心即可

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN=100005;
const double EPS=0.000000001;

int n,cnt;
double tmp,sa,sb,A,B;

struct Node {
    int index,g,a,b;

    bool operator < (const Node& x) const {//按照a/b的降序排列
        return a*x.b>x.a*b;
    }
}ing[MAXN];

double ans[MAXN];

int main() {
    freopen("burrito.in","r",stdin);
    freopen("burrito.out","w",stdout);
    while(3==scanf("%d%lf%lf",&n,&A,&B)) {
        for(int i=1;i<=n;++i) {
            scanf("%d%d%d",&ing[i].g,&ing[i].a,&ing[i].b);
            ing[i].index=i;
        }
        sort(ing+1,ing+1+n);
        memset(ans,0,sizeof(ans));
        sa=sb=0;
        cnt=0;
        for(int i=1;i<=n;++i) {
            tmp=ing[i].g*ing[i].b;
            if(tmp+sb-EPS<=B) {
                sa+=ing[i].g*ing[i].a;
                sb+=tmp;
                ans[ing[i].index]=ing[i].g;
            }
            else {
                if(sb+EPS<B) {
                    ans[ing[i].index]=(B-sb)/ing[i].b;
                    sa+=ans[ing[i].index]*ing[i].a;
                    sb=B;
                }
                break;
            }
        }
        if(sa+EPS<A) {
            printf("-1 -1\n");
            continue;
        }
        printf("%.8lf %.8lf\n%.8lf",sa,sb,ans[1]);
        for(int i=2;i<=n;++i) {
            printf(" %.8lf",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

Problem F. Filter (模拟)



题目大意:01串的长度为m,哈希参数有f个,共有n个压缩成16进制的01串(16进制的第一个数字对应01串的0~3,以此类推【注意:权重低的位在前】,若m%4!=0,则16进制的最后一位的转成的01串共凑成m位即可),当且仅当用户u对所有的哈希参数使得下标为(u*a[1~f])%m的01串的位上为1,该01串包含用户u,共有q个用户,求哪些串至少包含一个用户?

直接按照题目意思模拟即可

#include <cstdio>
#include <cstring>

using namespace std;

int n,m,f,q,cur,cnt;
int bit[1005][1005];
int num[127],ans[1005];
long long a[105],u[1005];
char s[255];
bool flag;

int main() {
    freopen("filter.in","r",stdin);
    freopen("filter.out","w",stdout);

    for(int i=0;i<=9;++i) {
        num[i+'0']=i;
    }
    for(int i=0;i<6;++i) {
        num[i+'a']=i+10;
    }
    while(2==scanf("%d%d",&m,&f)) {
        for(int i=0;i<f;++i) {
            scanf("%lld",a+i);
        }
        scanf("%d",&n);
        for(int i=0;i<n;++i) {
            scanf("%s",s);
            int j=0;
            for(;s[j+1]!='\0';++j) {
                cur=num[s[j]];
                for(int k=0;k<=3;++k) {//权重低的位在前
                    bit[i][(j<<2)+k]=cur%2;
                    cur/=2;
                }
            }
            cur=num[s[j]];
            for(int k=0;k<=(m+3)%4;++k) {//权重低的位在前
                bit[i][(j<<2)+k]=cur%2;
                cur/=2;
            }
        }
        scanf("%d",&q);
        for(int i=0;i<q;++i) {
            scanf("%lld",u+i);
        }
        cnt=0;
        for(int i=0;i<n;++i) {
            for(int j=0;j<q;++j) {
                flag=false;
                for(int k=0;k<f;++k) {
                    if(bit[i][(u[j]*a[k])%m]!=1) {
                        flag=true;
                        break;
                    }
                }
                if(!flag) {
                    ans[cnt++]=i;
                    break;
                }
            }
        }
        printf("%d",cnt);
        for(int i=0;i<cnt;++i) {
            printf(" %d",ans[i]);
        }
        printf("\n");
    }
    return 0;
}



Problem J. Jokewithpermutation (DFS)


题目大意:给定一个1~n的排列,不含空格,输出拆分后的该排列。

由于大部分状态均不合法,所以直接dfs即可

貌似看到可以用DP做,再研究研究

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN=100005;
const double EPS=0.000000001;

char s[105];
int num[55],n,len;
bool vis[105];

bool dfs(int pos,int cnt) {//pos为当前位置,cnt表示已找出的数的个数
    if(cnt==n) {//如果已找出n个数,并且字符串已遍历完,则当前结果合法
        return pos==len;
    }
    int cur=s[pos]-'0';//一位数
    if(!vis[cur]) {
        vis[cur]=true;
        num[cnt]=cur;
        bool flag=dfs(pos+1,cnt+1);
        vis[cur]=false;
        if(flag) {
            return true;
        }
    }

    ++pos;
    if(pos==len) {
        return false;
    }
    cur=cur*10+s[pos]-'0';//两位数
    if(!vis[cur]) {
        vis[cur]=true;
        num[cnt]=cur;
        bool flag=dfs(pos+1,cnt+1);
        vis[cur]=false;
        if(flag) {
            return true;
        }
    }
    return false;
}

int main() {
    freopen("joke.in","r",stdin);
    freopen("joke.out","w",stdout);
    while(1==scanf("%s",s)) {
        len=strlen(s);
        n=len<=9?len:9+(len-9)/2;
        vis[0]=true;
        for(int i=1;i<=n;++i) {
            vis[i]=false;
        }
        for(int i=n+1;i<105;++i) {//因为包含2位数,所以要将所有的2位数都初始化
            vis[i]=true;
        }
        dfs(0,0);
        printf("%d",num[0]);
        for(int i=1;i<n;++i) {
            printf(" %d",num[i]);
        }
        printf("\n");
    }
    return 0;
}


Problem K. Knockout Racing (模拟)


题目大意:有n辆车,每辆车的速度均为1m/s,第i辆车在a[i]~b[i]间往返跑,初始在a[i]。有m次询问,每次有3个数:x、y和t,表示求在开始的t秒后,有多少车在[x,y]内?

由于数据范围很小,直接模拟即可

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN=1005;

int n,m,tmp,t,x,y,coord,cnt;
int a[MAXN],b[MAXN],d[MAXN];

int getCoord(int i) {//貌似b[i]一定大于a[i],不过题意没有表明
    if(d[i]>0) {
        tmp=t%(d[i]<<1);
        if(tmp<=d[i]) {
            return a[i]+tmp;
        }
        return b[i]+d[i]-tmp;
    }
    else {
        tmp=t%((-d[i])<<1);
        if(tmp<=d[i]) {
            return a[i]-tmp;
        }
        return a[i]-d[i]+tmp;
    }

}

int main() {
    freopen("knockout.in","r",stdin);
    freopen("knockout.out","w",stdout);
    while(2==scanf("%d%d",&n,&m)) {
        for(int i=0;i<n;++i) {
            scanf("%d%d",a+i,b+i);
            d[i]=b[i]-a[i];
        }
        while(m-->0) {
            cnt=0;
            scanf("%d%d%d",&x,&y,&t);
            for(int i=0;i<n;++i) {
                coord=getCoord(i);
                if(x<=coord&&coord<=y) {
                    ++cnt;
                }
            }
            printf("%d\n",cnt);
        }
    }
    return 0;
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值