Pro
Sco
预计得分: 100 + 100 + 30 = 230 100 + 100 + 30 = 230 100+100+30=230
实际得分: 100 + 100 + 30 = 230 100 + 100 + 30 = 230 100+100+30=230
Sol##
业务办理
贪心题。
按照最长等待时间升序排序,然后从头到尾模拟着跑一边就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct Per {
long long t , d;
};
Per c[100005];
long long n , ans , tim = 0;
inline long long mymax(long long a , long long b) { return a>b?a:b; }
inline long long exc(long long x) { return x<0?0:x; }
bool cmp(Per x , Per y) {
if(x.d == y.d)
return x.t < y.t;
return x.d < y.d;
}
int main() {
freopen("transact.in","r",stdin);
freopen("transact.out","w",stdout);
scanf("%lld",&n);
for(int i=1; i<=n; i++)
scanf("%lld",&c[i].t);
for(int i=1; i<=n; i++)
scanf("%lld",&c[i].d);
sort(c+1 , c+n+1 , cmp);
for(int i=1; i<=n; i++) {
tim += c[i].t;
ans = mymax(ans , exc(tim - c[i].d));
}
printf("%lld",ans);
return 0;
}
传球接力
第一次直接打了50分就去看第三题了,打完第三题的暴力又回来想出正解。
首先知道,n个点n条边,一定存在环。
我们深搜求出每一个环来……
(很久之前的模拟题,突然忘了当时怎么想的了……)
反正就是拓扑胡乱搞搞就能A。
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int L = 500005;
struct Node {
int to;
long long len;
};
Node e[L];
queue<int>q;
vector<int>d;
int n , s;
long long sum , pre[L] , ans , flag , cir[L] , top , is , vis[L] , ind[L] , dit[L];
inline long long mymax(long long a , long long b) { return a>b?a:b; }
void dfs1(int u) {
int v = e[u].to;
if(vis[v]==flag) {
s = v;
is = 1;
return ;
}
if(vis[v]) {
is = 0;
return ;
}
vis[v] = flag;
dfs1(v);
}
void dfs2(int u) {
cir[++top] = u;
sum += e[u].len;
pre[e[u].to] = e[u].len;
if(e[u].to == s)
return;
dfs2(e[u].to);
}
void topo() {
for(int i=1; i<=n; i++)
if(!pre[i]&&!ind[i])
q.push(i);
while(!q.empty()) {
int u , v;
u = q.front();
q.pop();
v = e[u].to;
if(!pre[v])
dit[v] = mymax(dit[v] , dit[u]+e[u].len);
else
d.push_back(u);
ind[v]--;
if(!ind[v])
q.push(v);
}
}
int main() {
freopen("pass.in","r",stdin);
freopen("pass.out","w",stdout);
scanf("%d",&n);
for(int i=1; i<=n; i++) {
int x;
long long y;
scanf("%d%lld",&x,&y);
e[i].to = x;
e[i].len = y;
ind[x]++;
}
for(int i=1; i<=n; i++) {
if(vis[i])
continue;
sum = 0; is = 0; flag++; top = 0;
dfs1(i);
if(is) {
dfs2(s);
for(int i=1; i<=top; i++) {
pre[cir[i]] = sum - pre[cir[i]];
ans = mymax(ans , pre[cir[i]]);
}
}
}
topo();
for(int i=0; i<d.size(); i++)
ans = mymax(ans , e[d[i]].len+pre[e[d[i]].to]+dit[d[i]]);
printf("%lld",ans);
return 0;
}
捡金币
貌似时间限制是3s……
如果1s的话 直接dp可以过80 还是很不错的
当时打的是30分的暴力分,然后推了一会dp,发现打错了,于是得了30的暴力分。
方程很好写,也很好时间,不多说了。
#include<iostream>
#include<cstdio>
using namespace std;
int n , C , W , T;
int dp[105][30][30][155] , ans , map[105][30][30];
inline long long mymax(long long a , long long b) { return a>b?a:b; }
int main() {
freopen("coin.in","r",stdin);
freopen("coin.out","w",stdout);
scanf("%d%d%d%d",&n,&C,&W,&T);
for(int i=1; i<=T; i++)
for(int j=1; j<=n; j++)
for(int k=1; k<=n; k++)
scanf("%d",&map[i][j][k]);
for(int i=1; i<=T; i++) {
for(int x=1; x<=n; x++) {
for(int y=1; y<=n; y++) {
for(int k=0; k<=W; k++) {
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x][y][k]+map[i][x][y]);
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x+1][y][k]+map[i][x][y]);
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x-1][y][k]+map[i][x][y]);
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x][y+1][k]+map[i][x][y]);
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x][y-1][k]+map[i][x][y]);
for(int m=1; m<=C; m++) {
if(k-m<0)
break;
int mov = 2*m;
if(x-mov>=1)
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x-mov][y][k-m]+map[i][x][y]);
if(x+mov<=n)
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x+mov][y][k-m]+map[i][x][y]);
if(y-mov>=1)
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x][y-mov][k-m]+map[i][x][y]);
if(y+mov<=n)
dp[i][x][y][k] = mymax(dp[i][x][y][k] , dp[i-1][x][y+mov][k-m]+map[i][x][y]);
ans = mymax(ans , dp[i][x][y][k]);
}
}
}
}
}
printf("%d",ans);
return 0;
}