[codeforces][gym101873]2017-2018 ACM-ICPC German Collegiate Programming Contest (GCPC 2017)

队内训练
6题:CDFGIK

C.
nn<=1000 n ( n <= 1000 ) 个游乐场 mm<=1000 m ( m <= 1000 ) 条双向边,边长都为 TT<=1000 T ( T <= 1000 ) ,每个游乐场有一个游乐设施,玩一次第 i i 个游乐场的游乐设施耗时 ti t i ,花费 pi p i 的钱, 1<=ti,pi<=106 ( 1 <= t i , p i <= 10 6 ) 你可以在一个游乐场玩至少一次游乐设施,你从游乐场1出发,再回到游乐场1,花费时间恰好为 XX<=1000 X ( X <= 1000 ) 的最少花费是多少,如果不存在时间刚好为X的方案则输出“It is a trap.”

题解: 分层图最短路, dis[t][i] d i s [ t ] [ i ] 表示到 i i 点用时恰好为 t t 的最少花费金钱。

#include
#define LiangJiaJun main
#define ll long long
#define INF 1999122700000000LL
#define pa pair
using namespace std;
queueq;
int X,ti,n,m,ne,h[1004];
struct edge{
    int to,nt;
}e[20004];
void add(int u,int v){
     e[++ne].to=v;e[ne].nt=h[u];
     h[u]=ne;
}
int t[1004],p[1004];
ll dis[1004][1004];
bool inq[1004][1004];
int w33ha(){
    ne=0;
    memset(h,0,sizeof(h));
    scanf("%d%d%d",&n,&m,&ti);
    for(int i=1;i<=m;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++)scanf("%d%d",&t[i],&p[i]);
    for(int i=0;i<=1001;i++)
        for(int j=0;j<=1001;j++)
            dis[i][j]=INF;
    dis[t[1]][1]=p[1];
    q.push(make_pair(t[1],1));
    inq[t[1]][1]=1;
    while(!q.empty()){
        pa x=q.front();q.pop();
        int gt=x.first,gp=x.second;
        if(gt+t[gp]<=X){
            if( dis[gt+t[gp]][gp]>dis[gt][gp]+p[gp]){
                dis[gt+t[gp]][gp]=dis[gt][gp]+p[gp];
                if(!inq[gt+t[gp]][gp]){
                    inq[gt+t[gp]][gp]=1;
                    q.push(make_pair(gt+t[gp],gp));
                }
            }
        }
        for(int i=h[gp];i;i=e[i].nt){
            int tim=gt+ti+t[e[i].to];
            if(tim>X)continue;
            if( dis[tim][e[i].to]>dis[gt][gp]+p[e[i].to]){
                dis[tim][e[i].to]=dis[gt][gp]+p[e[i].to];
                if(!inq[tim][e[i].to]){
                    inq[tim][e[i].to]=1;
                    q.push(make_pair(tim,e[i].to));
                }
            }
        }
        inq[gt][gp]=0;
    }
    if(dis[X][1]==INF)return puts("It is a trap."),0;
    else printf("%lld\n",dis[X][1]);
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d",&X)!=EOF)w33ha();
    return 0;
}

D.队友写的(DFS)
F.队友写的+1(二分图匹配)
G.队友写的+2(皮克定理)
I.给 n n 个物品,从中取若干个物品,第 i i 个物品价值为 xi x i ,任意两个物品距离 >=m >= m ,问最大取到的物品价值总和。第一个能取的物品的位置是 m+1 m + 1
(n<=300000,m<=10,xi<=32) ( n <= 300000 , m <= 10 , x i <= 32 )

题解:简单DP

#include
#define LiangJiaJun main
#define ll long long
using namespace std;
int n,m;
int x[300004];
int f[300004][14];
int w33ha(){
    for(int i=1;i<=n;i++)scanf("%d",&x[i]);
    memset(f,0,sizeof(f));
    int ans=0;
    for(int i=m+1;i<=n;i++){
        for(int j=1;j1]=max(f[i][j+1],f[i-1][j]);
        }
        f[i][m]=max(f[i][m],f[i-1][m]);
        f[i][1]=max(f[i][1],f[i-1][m]+x[i]);
        for(int j=1;j<=m;j++)ans=max(ans,f[i][j]);
    }
    printf("%d\n",ans);
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d%d",&n,&m)!=EOF)w33ha();
    return 0;
}

K. n n 个人问至多删掉 k k 个人使得被删掉的人的工资总和 >=d >= d
签到题(不知为何wa3发,换了写法就A了)

#include
#define LiangJiaJun main
#define ll long long
using namespace std;
int n,k,d;
struct Ds{
    char s[14];
    int v;
}a[10004];
inline bool dex(Ds A,Ds B){return A.v>B.v;}
int w33ha(){
    for(int i=1;i<=n;i++){
        scanf("%s",a[i].s+1);
        scanf("%d",&a[i].v);
    }
    sort(a+1,a+n+1,dex);
    int kit=-1,sum=0;
    for(int i=1;i<=k;i++){
        sum+=a[i].v;
    }
    if(sumreturn puts("impossible"),0;
    else{
        printf("%d\n",k);
        for(int i=1;i<=k;i++){
            printf("%s, YOU ARE FIRED!\n",a[i].s+1);
        }
        return 0;
    }
    return 0;
}
int LiangJiaJun(){
    while(scanf("%d%d%d",&n,&d,&k)!=EOF)w33ha();
    return 0;
}

你可能感兴趣的:(深搜,二分图匹配,递推,spfa,最短路)