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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

posted @ 2018-10-29 19:15  jack_yyc  阅读(193)  评论(0编辑  收藏  举报