队内训练
6题:CDFGIK
C.
有n(n<=1000)n(n<=1000)个游乐场m(m<=1000)m(m<=1000)条双向边,边长都为T(T<=1000)T(T<=1000),每个游乐场有一个游乐设施,玩一次第ii个游乐场的游乐设施耗时,花费pipi的钱,(1<=ti,pi<=106)(1<=ti,pi<=106)你可以在一个游乐场玩至少一次游乐设施,你从游乐场1出发,再回到游乐场1,花费时间恰好为X(X<=1000)X(X<=1000) 的最少花费是多少,如果不存在时间刚好为X的方案则输出“It is a trap.”
题解: 分层图最短路,dis[t][i]dis[t][i] 表示到ii点用时恰好为的最少花费金钱。
#include<bits/stdc++.h>
#define LiangJiaJun main
#define ll long long
#define INF 1999122700000000LL
#define pa pair<int,int>
using namespace std;
queue<pa>q;
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.给nn个物品,从中取若干个物品,第个物品价值为xixi,任意两个物品距离>=m>=m,问最大取到的物品价值总和。第一个能取的物品的位置是m+1m+1
(n<=300000,m<=10,xi<=32)(n<=300000,m<=10,xi<=32)
题解:简单DP
#include<bits/stdc++.h>
#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;j<m;j++){
f[i][j+1]=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.nn个人问至多删掉个人使得被删掉的人的工资总和>=d>=d
签到题(不知为何wa3发,换了写法就A了)
#include<bits/stdc++.h>
#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(sum<d)return 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;
}