10.29 模拟赛
再次爆炸.模拟赛
T1 defile
题目大意:
假你本回合拥有 M 个随从且均可以攻击,其中第 i 个随从的攻击力为 A2[i],生命值为 B2[i] 对手拥有N个随从,其中第i个随从的攻击力为 A1[i],生命值为B1[i]
每次可以选择一个属于你的攻击力不为0 且未攻击过的随从攻击对手的某个未死亡的随从,每次攻击后双方的随从各受到等同于敌人攻击力的伤害
亵渎: 对所有随从造成 1 点伤害,若有随从死亡,则重新释放该法术 如果释放后 所有随从均死亡,则成功打出了一次“教科书般的亵渎
求能否通过操作随从指定的敌方随从来达成一次“教科书般 的亵渎”
思路:
爆搜 但是忘了攻击力不能为0的随从才能攻击
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 15 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 //yyc score=0 22 int n,m,a[MAXN][2],b[MAXN][2],hsh[MAXN<<1],vis[MAXN],ok; 23 int cheque() 24 { 25 memset(hsh,0,sizeof(hsh));ok=0; 26 for(int i=1;i<=n;i++) hsh[a[i][0]]=1,ok|=(a[i][0]>0); for(int i=1;i<=m;i++) hsh[a[i][1]]=1,ok|=(a[i][1]>0); 27 if(!ok) return 1; 28 if(!hsh[1]) return 0; 29 for(int i=2;i<=25;i++) if(hsh[i]&&!hsh[i-1]) return 0; 30 return 1; 31 } 32 void dfs(int x) 33 { 34 //for(int i=1;i<=n;i++) cout<<a[i][0]<<" ";puts(""); 35 //for(int i=1;i<=m;i++) cout<<a[i][1]<<" ";puts("\n"); 36 if(cheque()) {puts("Yes");exit(0);} 37 if(x==m+1) return ; 38 if(b[x][1]>0) 39 { 40 for(int i=1;i<=n;i++) 41 if(a[i][0]>0) 42 { 43 a[i][0]-=b[x][1],a[x][1]-=b[i][0]; 44 dfs(x+1); 45 a[i][0]+=b[x][1],a[x][1]+=b[i][0]; 46 } 47 } 48 dfs(x+1); 49 } 50 int main() 51 { 52 freopen("defile.in","r",stdin); 53 freopen("defile.out","w",stdout); 54 n=read(),m=read(); 55 for(int i=1;i<=n;i++) b[i][0]=read(),a[i][0]=read(); 56 for(int i=1;i<=m;i++) b[i][1]=read(),a[i][1]=read(); 57 dfs(1);puts("No"); 58 }
T2 treasure
题目大意:
一个寻宝游戏的目的是在有限的时间内寻到尽量多的宝藏
游戏的地图是一个n行m列的网格,每个网格可能是“.”、“#”、“*”、“S”四种字符的一 种,分别表示空地、障碍、宝藏点和玩家位置
角色每秒可以向上下左右移动一格,不能走出边界或走到障碍上
当走到了一个宝藏点时,她可以瞬间收集这里的宝藏
共有T + 0.5秒时间行动,当时间截至游戏就会结束。求游戏结束之前收 集尽量多的宝藏(即到达的不同的宝藏点尽量多)
思路:
每个宝藏点bfs求一下距离
状压水题
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 101010 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 //yyc score=0 22 int n,m,k,T,x[20],y[20],dx[4]={1,0,-1,0},dy[4]={0,1,0,-1}; 23 char mp[520][520]; 24 int qx[260010],qy[260010],l,r,ans; 25 int vis[520][520],dis[24][24],dp[1<<17][17]; 26 int ok(int a,int b) {return a&&b&&a<=n&&b<=m&&(mp[a][b]!='#');} 27 void bfs(int t) 28 { 29 qx[l=r=1]=x[t],qy[1]=y[t]; 30 memset(vis,0,sizeof(vis));int a,b; 31 while(l<=r) 32 { 33 a=qx[l],b=qy[l++]; 34 for(int i=0;i<4;i++) 35 if(ok(a+dx[i],b+dy[i])&&!vis[a+dx[i]][b+dy[i]]) 36 vis[a+dx[i]][b+dy[i]]=vis[a][b]+1,qx[++r]=a+dx[i],qy[r]=b+dy[i]; 37 } 38 for(int i=t+1;i<=k;i++) dis[t][i]=dis[i][t]= vis[x[i]][y[i]]==0?inf:vis[x[i]][y[i]]; 39 } 40 int main() 41 { 42 freopen("treasure.in","r",stdin); 43 freopen("treasure.out","w",stdout); 44 n=read(),m=read(),k=read(),T=read();int a=0; 45 for(int i=1;i<=n;i++) 46 { 47 scanf("%s",mp[i]+1); 48 for(int j=1;j<=m;j++) 49 if(mp[i][j]=='*') x[a]=i,y[a++]=j; 50 else if(mp[i][j]=='S') x[k]=i,y[k]=j; 51 } 52 for(int i=0;i<=k;i++) bfs(i); 53 memset(dp,127,sizeof(dp)); 54 for(int i=0;i<k;i++) dp[1<<i][i]=0; 55 for(int i=1;i<(1<<k);i++) 56 for(int j=0;j<k;j++) 57 if(!((1<<j)&i)) 58 for(int o=0;o<k;o++) 59 if((1<<o)&i) 60 if(dis[o][j]!=inf)dp[i|(1<<j)][j]=min(dp[i|(1<<j)][j],dp[i][o]+dis[o][j]); 61 for(int t,cnt,i=1;i<(1<<k);i++) 62 { 63 t=inf,cnt=0; 64 for(int j=0;j<k;j++) if((1<<j)&i) 65 if(dp[i][j]!=inf)t=min(t,dis[j][k]+dp[i][j]),cnt++; 66 if(t<=T) ans=max(ans,cnt); 67 } 68 printf("%d",ans); 69 }
T3 instrument
题目大意:
一个数列 划分成若干段使每段内无相同的数
最短段的长度的最大值 以及满足这个条件的方案数
思路:
可以二分求出第一问的解 在判断可行的时候可以顺便求出第二问
即用dp i表示最后一段以i为结尾的方案数 转移的时候可以从pre ~ i-x转移过来
前缀和优化一下 判断最终dp值是否为0 即可check
(但写法出现了一些偏差)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 530010 13 #define MOD 998244353 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} 19 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 20 return x*f; 21 } 22 //yyc score= 0 23 int n,a[MAXN],b[MAXN],c[MAXN],pre[MAXN]; 24 ll ans,res,dp[MAXN],sum[MAXN]; 25 ll cheque(int x) 26 { 27 for(int i=1;i<=x;i++) dp[i]=sum[i]=0; 28 for(int i=x;i<=n;i++) 29 { 30 if(i-pre[i]<x) {dp[i]=0,sum[i]=sum[i-1];continue;} 31 if(!pre[i]) {dp[i]=sum[i-x]+1,sum[i]=sum[i-1]+dp[i];continue;} 32 dp[i]=(sum[i-x]-(pre[i]==0?0:sum[pre[i]-1])+MOD)%MOD; 33 if(dp[i]>2*MOD) dp[i]-=MOD; 34 sum[i]=(sum[i-1]+dp[i])%MOD; 35 } 36 return dp[n]>0; 37 } 38 int main() 39 { 40 freopen("instrument.in","r",stdin); 41 freopen("instrument.out","w",stdout); 42 n=read();int l,r,mid; 43 for(int i=1;i<=n;i++) a[i]=b[i]=read(); 44 sort(b+1,b+n+1);l=unique(b+1,b+n+1)-b-1; 45 for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+l+1,a[i])-b; 46 for(int i=1;i<=n;i++) pre[i]=c[a[i]],c[a[i]]=i,pre[i]=max(pre[i],pre[i-1]); 47 l=1,r=n; 48 while(l<=r) 49 { 50 mid=l+r>>1; 51 if(cheque(mid)) ans=mid,res=dp[n],l=mid+1; 52 else r=mid-1; 53 } 54 printf("%lld\n%lld",ans,res%MOD); 55 }