【FJOI 20170305】省选模拟赛

题面被改成了个猪。。。


 

T1猪猪划船(boat)

【题目描述】

6只可爱的猪猪们一起旅游,其中有3只大猪A,B,C,他们的孩子为3只小猪a,b,c。由于猪猪们十分凶残,如果小猪在没有父母监护的情况下,和其他的大猪待在一起,就会被吃掉。

拦在他们面前的是一条大河,河上有一只只有1个船桨且限载2只猪的小船,只有A,B,C,a会划船。他们独自划船单程需要的时间为tA,tB,tC,ta,如果搭载另一只猪时间翻倍。你需要求出所有猪猪过河的最短时间。

【输入数据】

一行,4个整数,tA,tB,tC,ta。

【输出数据】

一行,一个整数,表示最短时间。

【样例输入】

10 10 10 10

【样例输出】

220

【数据范围】

对于20%的数据:tA=tB=tC=ta

对于60%的数据:ta<=tA<=tB<=tC

对于100%的数据:tA,tB,tC,ta<=100

【题解大意】

写的时候没推懂样例。然后因为样例给的是tA=tB=tC=ta,所以交了一个无脑的20分,直接输出22*t。

一直到讲之前也还是没弄懂样例。。。

【code】

//boat.20
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(k,i,j) for(int k = i;k <= j; ++k)
#define FOR(k,i,j) for(int k = i;k >= j; --k)
inline void file(){
    freopen("boat.in","r",stdin);
    freopen("boat.out","w",stdout);
}
inline int read(){
    int x=0,f=1;   char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
const int mxn = 200;
int val[5];
inline int A(int x){return x&(1<<1)>0;}
inline int B(int x){return x&(1<<2)>0;}
inline int C(int x){return x&(1<<3)>0;}
inline int a(int x){return x&(1<<4)>0;}
inline int b(int x){return x&(1<<5)>0;}
inline int c(int x){return x&(1<<6)>0;}
inline bool check(int x){
    if(A(x)!=a(x))
        if(a(x)==B(x)||a(x)==C(x)) return 0;
    if(B(x)!=b(x))
        if(b(x)==A(x)||a(x)==C(x)) return 0;
     if(C(x)!=c(x))
        if(c(x)==A(x)||c(x)==B(x)) return 0;
    return 1;
}
bool v[mxn];
int d[mxn];
queue<int>q;
inline void wor(int x,int y,int z){
    if(!check(y)) return;
    if(d[y] > d[x]+z){
        d[y] = d[x]+z;
        if(!v[y]) q.push(y),v[y] = 1;
    }
}
inline void spfa(){
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    v[0] = 1,d[0] = 0;
    q.push(0);
    while(q.size()){
        int x = q.front(); q.pop();
        if(x&1){
            rep(i,1,4) if(x&(1<<i))
                rep(j,1,6) if(x&(1<<j))
                    if(i==j) wor(x,x^(1<<i)^1,val[i]<<1);
                    else wor(x,x^(1<<i)^(1<<j)^1,val[i]<<1);
        }else{
            rep(i,1,4) if(!(x&(1<<i)))
                rep(j,1,6) if(!(x&(1<<j)))
                    if(i==j) wor(x,x^(1<<i)^1,val[i]<<1);
                    else wor(x,x^(1<<i)^(1<<j)^1,val[i]<<1);
        }
    }
}
int main(){
//    file();
    rep(i,1,4) val[i] = read();
    spfa();
    printf("%d\n",d[(1<<7)-1]);
    return 0;
}
View Code

 

 

 T2小猪星球(planet)

【题目描述】

小猪所在的星系有n个星球,用1~n标号,其中有一些星球之间有单向的隧道相连。由于超时空隧道的存在,通过一个隧道的时间可能为0或负数。现在小猪们决定从1号星球出发,沿着最短路径到达n号星球。

科学家猪小聪发明了一种神奇的装置,使得飞船在每个隧道中运行的时间都增加一个相同的常数(可以为0或负数),你需要确定这个常数使得旅途的总时间非负且最小。

【输入数据】

输入文件包含多组数据,第一行为数据组数T。

对于每一组数据,第一行两个整数V,E,表示星球的个数和隧道的个数。接下来E行,每行3个整数i,j,t,表示从i号星球到j号星球有一条耗时为t的单向隧道。

【输出数据】

共T行,每行一个整数,表示从1号星球到n号星球最短的时间。如果不能从1号星球到达n号星球,输出-1。

【样例输入】

1

4 5

1 2 1

1 3 1

2 3 -3

3 1 1

3 4 1

【样例输出】

2

【样例解释】

如果不使用科技(也可以理解成是使用科技,但确定常数为0,所有的隧道时间不变),则1->2->3->1->2->3……->4的时间为负无穷,不符合要求。若使用科技,确定常数为1,则1->2->3->4的最短时间为2。

【数据范围】

对于100%的数据,N<=100,E<=N(N+1)/2,|t|<=10^5,i,j<=N

友情提示:可能有重边和自环

【题解大意】

写了两个小时还是爆零的题,真是令人开心。

【code】

//planet
#include<bits/stdc++.h>
using namespace std;
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define rep(k,i,j) for(int k = i;k <= j; ++k)
#define FOR(k,i,j) for(int k = i;k >= j; --k)
inline void file(){
    freopen("planet.in","r",stdin);
    freopen("planet.out","w",stdout);
}
inline int read(){
    int x=0,f=1;   char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
const int mxn = 105;
const int lim = 1e5;
int T,V,E;
bool v[mxn],vis[mxn];

struct edge{int nxt,y,v;}e[lim];
struct eg{int nxt,y;}e1[lim];

int to[mxn],len;
inline void add(int xx,int yy,int zz){
    e[++len].nxt = to[xx];
    to[xx] = len;
    e[len].y = yy;
    e[len].v = zz;
}
int to1[mxn],len1;
inline void add1(int x,int y){
    e1[++len1].nxt = to1[x];
    to1[x] = len1;
    e1[len1].y = y;
}

int d[mxn];
queue<int> q;
int cnt[mxn];
bool a[mxn][mxn];

inline void dfs(int x){
    vis[x] = 1;
    for(int i = to1[x]; i;i = e1[i].nxt){
        int y = e1[i].y;
        if(!vis[y]) dfs(y);
    }
}

inline void Floyd(){
    memset(vis,0,sizeof(vis));
    rep(k,1,V)rep(i,1,V)rep(j,1,V)
    a[i][j] |= a[i][k]&a[k][j];
    //连通为 1,不连通为 0
    rep(i,1,V-1) if(!a[i][V]) vis[i] = 1;
}

inline bool spfa(int dt){
    memset(cnt,0,sizeof(cnt));
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    v[1] = 1,d[1] = 0,cnt[1] = 1;
    q.push(1);
    while(q.size()){
        int x = q.front(); q.pop();
        v[x] = 0;
        for(int i = to[x]; i;i = e[i].nxt){
            int y = e[i].y,z = e[i].v+dt;
            if(vis[y]) continue;
            if(d[y] > d[x]+z){
                d[y] = d[x]+z;
                cnt[y] = cnt[x]+1;
                if(cnt[y] > V) return 0;
                if(!v[y]) q.push(y),v[y] = 1;
            }
        }
    }
    return d[V]>=0;
}
int l,r,m;
inline int wor(){
    if(vis[1]) return -1;
    l = -lim,r = lim;
    while(l+1<r){
        m = l+r >>1;
        spfa(m)?r = m:l = m+1;
    }
    if(spfa(l)) return d[V];
    spfa(r); return d[V];
}
inline void clear(){
    len = 0,len1 = 0;
    memset(to,0,sizeof to);
    memset(to1,0,sizeof to1);
    memset(vis,0,sizeof vis);
}
int main(){
//    file();
    T = read();
    while(T--){
        V = read(),E = read();
        memset(a,0,sizeof(a));
        clear();
        while(E--) {
            int i = read(),j = read(),t = read();
            a[i][j] = 1;
            add(i,j,t);
//            add1(j,i);
        }
//        dfs(V);
        Floyd();
        printf("%d\n",wor());
    }
    return 0;
}
View Code

 

 

T3小猪送货(deliver)

【题目描述】

小猪所在的星系有n个星球从左到右排成一排,用1~n标号。每个星球有建设有一个工厂,住着若干居民。猪粮是猪猪星系的重要的物资,第i个城市的工厂能够生产pi个单位的猪粮,第i个城市最多可以卖出si个单位猪粮。对于任意1<=i<j<=n,存在着一条从i到j的单向道路,最多可以通过这条道路运输c个单位的猪粮,你需要计算最多能够卖出多少猪粮。

【输入数据】

第一行两个整数n,c

第二行n个整数,第i个整数表示pi

第三行n个整数,第i个整数表示si

【输出数据】

一行,一个整数,表示最多可以卖出的猪粮的单位数

【样例输入1】

5 1

7 4 2 1 0

1 2 3 4 5

【样例输出1】

12

【样例输入2】

4 3

13 10 7 4

4 7 10 13

【样例输出2】

34

【数据范围】

对于20%的数据:c=0

对于60%的数据:n<=100

对于100%的数据:n<=10000,0<=c,pi,si<=10^9

【题解大意】

拿了c=0的部分分,每次加上min(p[i],s[i])就行,正确性显然。

本题来源:codeforces 724E

【code】

#include<bits/stdc++.h>
using namespace std;
#define inf 1<<30
#define ll long long
#define ull unsigned long long
#define rep(k,i,j) for(int k = i;k <= j; ++k)
#define FOR(k,i,j) for(int k = i;k >= j; --k)
inline void file(){
    freopen("deliver.in","r",stdin);
    freopen("deliver.out","w",stdout);
}
inline int read(){
    int x=0,f=1;   char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
const int mxn = 1e4+5;
int p[mxn],s[mxn];
int n,c;
int f[mxn][mxn];
int main(){
    file();
    n = read(),c = read();
    rep(i,1,n) p[i] = read();
    rep(i,1,n) s[i] = read();
    rep(i,1,n) f[0][i] = f[1][i] = inf;
    f[1][0]=p[1],f[1][1]=s[1];
    rep(i,2,n){
        f[i&1][0] = f[i&1^1][0]+p[i];
        rep(j,1,n){
            f[i&1][j] = min(f[i&1^1][j]+j*c+p[i],f[i&1^1][j-1]+s[i]);
        }
    }
    int minx = inf;
    rep(i,0,n) minx = min(minx,f[n&1][i]);
    printf("%d\n",minx);
    return 0;
}
View Code

 

 

T4小猪数数(math)

【题目描述】

猪小聪和猪小明在一个小时的时间里,A完了前三题,他们无聊地说:“咱们来玩个游戏消磨时间吧……”

在这个游戏中,猪小聪和猪小明每个人手上有一台电脑,一开始双方的电脑上的数字都是1。现在猪小聪和猪小明按照任意的顺序执行操作a=a+b(其中a为自己电脑上的数字,b为对方电脑上的数字),例如按照小聪-小明-小明执行后双方的数字为2 5。

现在在他们玩了若干轮之后,双方电脑上的数字为N M,可惜的是他们忘记了他们到底玩了多少轮,你需要求出他们至少玩了多少轮。

【输入数据】

2个整数,表示N,M。

【输出数据】

1个整数,表示最少玩过的轮数。如果根本不可能出现符合要求的结果,输出-1。

【样例输入1】

2 5

【样例输出1】

3

【样例输入2】

2 2

【样例输出2】

-1

【数据范围】

对于30%的数据,1<=N,M<=10

对于60%的数据,1<=N,M<=1000

对于100%的数据:N,M和ans均不会爆long long (ans表示输出的答案)

【题解大意】

考虑怎么把给定的两个数给弄回去,辗转相减之类的就好了,然后看最后能不能减到n=1,m=1

最后一题这么来好假。。。

【code】

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(k,i,j) for(int k = i;k <= j; ++k)
#define FOR(k,i,j) for(int k = i;k >= j; --k)
inline void file(){
    freopen("math.in","r",stdin);
    freopen("math.out","w",stdout);
}
inline int read(){
    int x=0,f=1;   char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
ll n,m,tot = 0;
inline void work(){
    bool f = 1;
    while(m>0&&n>0){
        if(m==1&&n==1) break;
        m -= n;
        if(m==0||n==0) {
            f = 0;
            break;
        }
        ++tot;
        if(m<n) swap(m,n);
    }
    if(f) printf("%lld\n",tot);
    else puts("-1");
}
int main(){
//    file();
    scanf("%lld %lld",&n,&m);
    if(n>m) swap(n,m);
    if(n==m&&n!=1) {
        puts("-1");
        return 0;
    }
    if(n==m&&n==1){
        puts("0");
        return 0;
    }
    work();
    return 0;
}
View Code

 

posted @ 2019-03-08 20:32  ve-2021  阅读(180)  评论(0编辑  收藏  举报