codeforces contest 358

http://codeforces.com/contest/358



//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

A 358A Dima and Continuous Line

题意:

题解:mdzz 想复杂了,wa了一万年。我可能是个傻逼。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int N=1005;
int a[N];
struct Node {
    int x,y;
}b[N];
int main() {
    int n;
    while(~scanf("%d",&n)) {
        for(int i=1;i<=n;++i) scanf("%d",&a[i]);
        for(int i=1;i<n;++i) {
            int x=a[i],y=a[i+1];
            if(x>y) swap(x,y);
            b[i].x=x;
            b[i].y=y;
        }
        --n;

        int ans=0;

        for(int i=1;i<=n;++i) {
            for(int j=1;j<=n;++j) {
                if(i==j) continue;
                int x1=b[i].x,y1=b[i].y;
                int x2=b[j].x,y2=b[j].y;
                if((x1<x2&&x2<y1&&y1<y2)||(x2<x1&&x1<y2&&y2<y1)) {
                    ans=1;
                    break;
                }
            }
        }

        if(ans) {
            puts("yes");
        } else {
            puts("no");
        }
    }
    return 0;
}


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

C 358C Dima and Containers

题意:三个容器。栈,队列,双端队列。

两种操作:

1、压入一个数在任意一个容器。

2、从三个容器中弹出一个数。(如果容器为空,不用弹出)。弹出后清空。

n次操作之后要让弹出的数总和最大。输出所有操作。

题解:模拟。最大的放在三个容器。其他的都放在双端队列的另一端。



#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005;
struct Node {
    int val,i,tag;
}a[N],b[N];
bool cmp1(Node a,Node b) {
    if(a.val==b.val) return a.i<b.i;
    return a.val>b.val;
}
bool cmp2(Node a,Node b) {
    return a.i<b.i;
}
int main() {
    int n;
    while(~scanf("%d",&n)) {
        int m=0;
        for(int i=1;i<=n;++i) {
            scanf("%d",&a[i].val);
            a[i].i=i;
            a[i].tag=0;
            b[++m]=a[i];
            if(a[i].val==0) {
                sort(b+1,b+m,cmp1);
                int cnt=0;
                for(int j=1;j<m&&j<=3;++j) {
                    b[j].tag=1;
                    ++cnt;
                }
                sort(b+1,b+m,cmp2);
                int p=0;
                for(int j=1;j<m;++j) {
                    if(b[j].tag) {
                        if(p==0) puts("pushStack");
                        else if(p==1) puts("pushQueue");
                        else if(p==2) puts("pushFront");
                        ++p;
                    } else {
                        puts("pushBack");
                    }
                }
                printf("%d",cnt);
                if(cnt>=1) printf(" popStack");
                if(cnt>=2) printf(" popQueue");
                if(cnt>=3) printf(" popFront");
                puts("");
                m=0;
            }
        }
        for(int i=1;i<=m;++i) puts("pushBack");
    }
    return 0;
}


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

D  358D  Dima and Hares
题意:喂n只兔子。给出三个数组。
a[i]表示喂第i只兔子时,它的左右都还没被喂的收益。
b[i]表示喂第i只兔子时,它的左右只被喂了一只的收益。
c[i]表示喂第i只兔子时,它的左右都被喂了的收益。
题解:
d[i][0][0] 表示喂第i只兔子时,它的左右都还没被喂。
d[i][0][1]表示喂第i只兔子时,它的右边被喂了。
d[i][1][0]表示喂第i只兔子时,它的左边被喂了。
d[i][1][1]表示喂第i只兔子时,它的左右都被喂了。
woc dp真的吼难啊!!!水平不够,还没办法参透这道题(下次做类似的不知道还能不能做出来)。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=3005;
int a[N][3],d[N][2][2];
int main() {
    int n;
    while(~scanf("%d",&n)) {
        for(int i=0;i<3;++i)
            for(int j=1;j<=n;++j)
                scanf("%d",&a[j][i]);
        d[1][1][0]=d[1][1][1]=-99999999;
        d[1][0][0]=a[1][0];
        d[1][0][1]=a[1][1];
        for(int i=2;i<=n;++i) {
            d[i][0][0]=max(d[i-1][0][1],d[i-1][1][1])+a[i][0];
            d[i][0][1]=max(d[i-1][0][1],d[i-1][1][1])+a[i][1];
            d[i][1][0]=max(d[i-1][0][0],d[i-1][1][0])+a[i][1];
            d[i][1][1]=max(d[i-1][0][0],d[i-1][1][0])+a[i][2];
        }
        printf("%d\n",max(d[n][0][0],d[n][1][0]));
    }
    return 0;
}


//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
E  358E  Dima and Kicks
题意:n*m的格子,1表示一定要走并且只能走一遍,0表示一定不能走。每次走k格,求k的所有取值。
题解:我们把能转弯的点当成结点。那么满足条件的图就是一个欧拉图(联通,奇度点0个或2个)。然后处理出所有的边,取gcd就行了。
#include<cstdio>
#include<cstring>
const int N=1005;
int a[N][N],duandian[N][N],vis[N][N];
int n,m;
int check(int x,int y) {
    int shang=a[x-1][y];
    int you=a[x][y+1];
    int xia=a[x+1][y];
    int zuo=a[x][y-1];
    int t=shang+you+xia+zuo;
    if(t==2) {
        if(shang&&xia) t=0;
        if(zuo&&you) t=0;
    }
    return t;
}
int gcd(int a,int b) {
    if(b==0) return a;
    return gcd(b,a%b);
}
void dfs(int x,int y) {
    vis[x][y]=1;
    int shang=a[x-1][y]&&!vis[x-1][y];
    int you=a[x][y+1]&&!vis[x][y+1];
    int xia=a[x+1][y]&&!vis[x+1][y];
    int zuo=a[x][y-1]&&!vis[x][y-1];
    if(shang) dfs(x-1,y);
    if(you) dfs(x,y+1);
    if(xia) dfs(x+1,y);
    if(zuo) dfs(x,y-1);
}
int main() {
    while(~scanf("%d%d",&n,&m)) {
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                scanf("%d",&a[i][j]);

        //欧拉图
        //1、判断联通
        memset(vis,0,sizeof(vis));
        int flag=1;
        for(int i=1;i<=n&&flag;++i)
            for(int j=1;j<=m&&flag;++j)
                if(a[i][j]) {
                    dfs(i,j);
                    flag=0;
                }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(a[i][j]&&!vis[i][j]) {
                    puts("-1");
                    return 0;
                }

        //2、奇度点的个数
        memset(duandian,0,sizeof(duandian));
        int cnt=0;
        for(int i=1;i<=n&&cnt<=2;++i) {
            for(int j=1;j<=m&&cnt<=2;++j) {
                if(!a[i][j]) continue;
                int t=check(i,j);
                if(t) duandian[i][j]=1;
                if(t&1) ++cnt;
            }
        }

        if(cnt==1||cnt>2) {
            puts("-1");
            continue;
        }

        //所有边的长度
        memset(vis,0,sizeof(vis));
        int ans=0;
        for(int i=1;i<=n;++i) {
            for(int j=1;j<=m;++j) {
                if(!duandian[i][j]) continue;
                int x=i,y=j;
                int shang=a[x-1][y]&&!vis[x-1][y];
                int you=a[x][y+1]&&!vis[x][y+1];
                int xia=a[x+1][y]&&!vis[x+1][y];
                int zuo=a[x][y-1]&&!vis[x][y-1];
                if(shang) {
                    int t=x-1;
                    while(a[t][y]&&!vis[t][y]&&!duandian[t][y]) --t;
                    ans=gcd(ans,x-t);
                }
                if(you) {
                    int t=y+1;
                    while(a[x][t]&&!vis[x][t]&&!duandian[x][t]) ++t;
                    ans=gcd(ans,t-y);
                }
                if(xia) {
                    int t=x+1;
                    while(a[t][y]&&!vis[t][y]&&!duandian[t][y]) ++t;
                    ans=gcd(ans,t-x);
                }
                if(zuo) {
                    int t=y-1;
                    while(a[x][t]&&!vis[x][t]&&!duandian[x][t]) --t;
                    ans=gcd(ans,y-t);
                }
            }
        }

        if(ans<=1) {
            puts("-1");
        } else {
            for(int i=2;i<=ans;++i) {
                if(ans%i==0) printf("%d ",i);
            }
            puts("");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值