noip模拟【2016】

T1

[贪心]

按照等待时间排序,然后记录最大不满意度即可。->复杂度正确O(nlogn),正确性未知。

可以考虑跟全排列的暴力拍一拍。数据好造。暴力好写。

再想5分钟O(n^2)的做法->想不出来。

一遍过小样例和大样例。突然不想拍。写完后面的题再拍。。

今日rank1选手被这题卡了ak哈哈哈。。

 【code】

#include
using namespace std;
#define ll long long 
#define File "transact"
inline void file(){
    freopen(File".in","r",stdin);
    freopen(File".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 = 1e5 + 5;
int n;
struct P{
    int t,d;
}p[mxn];

inline bool cmp(P t1,P t2){
    return t1.d < t2.d;
}

int main(){
    file();
    n = read();
    for(int i = 1;i <= n; ++i) p[i].t = read();
    for(int i = 1;i <= n; ++i) p[i].d = read();
    sort(p+1,p+n+1,cmp);
    ll s(0),mx(0);
    for(int i = 1;i <= n; ++i){
        s += (ll)p[i].t;
        if(s > (ll)p[i].d) mx = max(mx,s-(ll)p[i].d);
    }
    printf("%lld\n",mx);
    return 0;
}
View Code

 

 

T2

[拓扑?]

由于每个人接到球之后会把球传给谁是固定的,并且传球的距离也是固定的。

改变接球顺序来改变传球接力最长距离,就只是改变第一个发球人的顺序。

当球要传给一个已经拿到过球的人时,传球停止。

O(n^2)暴力 -> 50pts

可以想到这个图实际上是一棵树(有向)多一条边,要求该图的直径。

一个正确性靠谱但复杂度没了的做法。从每一个入度为零的点出发。

一个复杂度正确正确性未知的做法。建双向边,特殊处理,跑树的直径即可。

那就冷静一下之后写这两个程序。

然后正确性未知的做法果然是个垃圾。

想到实际上就是要处理一个环加上若干枝。

且必定从某个入度为零的点进入遍历。

这个环(少一条边)是无论如何都要遍历一遍的。

枚举断点,取max即可。

 【code】

#include
using namespace std;
#define ll long long 
#define File "pass"
inline void file(){
    freopen(File".in","r",stdin);
    freopen(File".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 = 5e5 + 5;
int n;
int in[mxn],cir[mxn];
ll a[mxn],d[mxn],b[mxn],f[mxn]; 

queue<int> q;
bool v[mxn];
ll tot(0),sum(0),ans(0);

int main(){
    file();
    n = read();
    for(int i = 1;i <= n; ++i){
        a[i] = read(),d[i] = read();
        in[a[i]]++;
    }
    for(int i = 1;i <= n; ++i) 
        if(!in[i]) q.push(i);
    
    while(!q.empty()){
        ll x = q.front(); q.pop();
        ll y = a[x];
        f[y] = max(f[y],f[x] + d[x]);
        if(!(--in[y]))    q.push(y);
    }
    
    for(int i = 1;i <= n; ++i){
        if(in[i] && !v[i]){
            ll k = a[i];
            
            cir[++tot] = i;
            b[a[i]] = d[i];
            sum = d[i];
            
            while(k != i){
                v[k] = 1;
                
                cir[++tot] = k;
                b[a[k]] = d[k]; 
                sum += d[k];
                
                k = a[k];                                         
            }//
            for(int j = 1;j <= tot; ++j)
                ans = max(ans,sum + f[cir[j]] - b[cir[j]]);
        }
    } 
    printf("%lld\n",ans);
    return 0;
}
/*
5
2 1
3 2
4 1
2 3
3 3
*/
View Code

 

 

T3

[dp]

考虑最暴力的暴力。

选择在哪一个方格开始游戏O(n^2)

向哪个方向走多少各O(4*n)

走到当前格子之后继续走。。

再次O(4*n)枚举

总共枚举T次。

总复杂度为O(n^2*4^T*n^T) -> 30pts

等哈。这莫不是个dp嘛。

然后就可以满分了。。

 【code】

#include
using namespace std;
#define ll long long 
#define File "coin"
inline void file(){
    freopen(File".in","r",stdin);
    freopen(File".out","w",stdout);
} 
inline ll read(){
    ll 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 = 30;
const int mxT = 105;
const int mxW = 155;
int n,C,W,T;
int dx[5] = {-1,1,0,0,0},dy[5] = {0,0,-1,1,0}; 

inline ll min_(ll x,ll y){
    return x < y ? x : y;
}
inline ll max_(ll x,ll y){
    return x > y ? x : y;
}
inline bool ok(int x,int y){
    if(x > 0 && x <= n && y > 0 && y <= n) return true;
    return false;
}
inline int x_(int i,int x,int c){
    if(!c) return x+dx[i];
    return x+2*c*dx[i];
}
inline int y_(int i,int y,int c){
    if(!c) return y+dy[i];
    return y+2*c*dy[i];
}

ll f[mxT][mxn][mxn][mxW];
ll a[mxn][mxn];
ll ans(0);
int main(){
    file();
    n = read(),C = min_(n/2,read()),W = read(),T = read();
///*
    memset(f,0xcf,sizeof f);

    for(int i = 1;i <= n; ++i)
        for(int j = 1;j <= n; ++j)
            f[0][i][j][0] = 0;
    
    for(int t = 1;t <= T; ++t){
        for(int i = 1;i <= n; ++i)
            for(int j = 1;j <= n; ++j)
                a[i][j] = read();
        
        for(int x = 1;x <= n; ++x)
            for(int y = 1;y <= n; ++y)
                for(int s = 0;s <= W; ++s)
                    for(int i = 0;i < 5; ++i)
                        for(int c = 0;c <= min_(C,s) && ok(x_(i,x,c),y_(i,y,c)) && (i!=4||!c); ++c)
                            f[t][x][y][s] = max_(f[t][x][y][s],f[t-1][x_(i,x,c)][y_(i,y,c)][s-c] + a[x][y]);        
    }
    
    for(int i = 1;i <= n; ++i)
        for(int j = 1;j <= n; ++j)
            for(int k = 0;k <= W; ++k)    
                ans = max_(ans,f[T][i][j][k]);
    printf("%lld\n",ans);             

    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/ve-2021/p/11357083.html

你可能感兴趣的:(noip模拟【2016】)