队内训练
6题:CDFGIK
C.
有 n(n<=1000) n ( n <= 1000 ) 个游乐场 m(m<=1000) m ( m <= 1000 ) 条双向边,边长都为 T(T<=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,花费时间恰好为 X(X<=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;
queue 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.给 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;
}