(本套题算是比较温和吧,就是罚时有点高。
B .Baby Bites
题意:给出一个婴儿给出的数组,有一些数字听不清楚,让你还原,问它是否是一个从1开始的一次增加的数组。
思路:从左往右依次固定,看是否有矛盾即可。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define rep2(i,a,b) for(int i=a;i>=b;i--) using namespace std; int a[1100]; char c[10]; int main() { int N; bool F=true; scanf("%d",&N); rep(i,1,N) { scanf("%s",c+1); if(c[1]=='m') a[i]=-1; else { int L=strlen(c+1); rep(j,1,L) a[i]=a[i]*10+c[j]-'0'; } } if(a[1]==-1) a[1]=1; if(a[1]!=1) F=false; rep(i,1,N) { if(a[i]==-1&&a[i-1]!=-1) a[i]=a[i-1]+1; if(a[i]!=-1&&a[i-1]!=-1) if(a[i]!=a[i-1]+1) F=false; } if(F) puts("makes sense"); else puts("something is fishy"); return 0; }
C .Code Cleanups
题意:给定N个物体,每个物品需要在第几天清扫。 你每次可以选择其中几个清扫,但是要满足你选择的集合拖欠的天数之和<20;问最小的清扫次数。
思路:贪心地取即可。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int a[1100]; int main() { int N,ans=0; scanf("%d",&N); rep(i,1,N) scanf("%d",&a[i]); rep(i,1,N){ int now=1,sum=0,j=i; ans++; while(j+1<=N&&(sum+now*(a[j+1]-a[j]))<20) sum+=now*(a[j+1]-a[j]),now++,j++; i=j; } printf("%d",ans); return 0; }
E. Explosion Exploit
题意:给定N个自己人,M个敌人。以及每个人的血量ai。系统一共发起K次攻击,每次随机选择一个人物进行攻击,被攻击后血量少1,血量为0的不再考虑。问最后敌人都被杀死的概率。 (N,M<=5 ,ai<=6,K<=100)
思路:因为数据都比较小,我们可以考虑记忆化搜索,显然我们不能开10维数组来模拟,空间不够。 我们需要维护两个集合,分别是自己人的血量和敌人的血量,然后记忆化搜索。 集合我们可以用vector来表示,每次向下搜索前vector可以先排序,这样可以减很多的枝。 我的代码没用数组表示集合,用的是long long。
因为魔改了几次,所以代码比较丑。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; map<ll,double>mp; int N,M,K; int a[13],b[13],sum,FCY; ll P[20]; int c[13],cnt; void Change(ll &x){ //集合内部排序 ll res=0; for(int i=N;i>=1;i--) a[i]=x%10,x/=10; for(int i=M;i>=1;i--) b[i]=x%10,x/=10; sort(a+1,a+N+1); sort(b+1,b+M+1); rep(i,1,M) res=res*10+b[i],c[N+M+1-i]=b[i]; rep(i,1,N) res=res*10+a[i],c[N+1-i]=a[i]; cnt=0; rep(i,1,N) if(a[i]) cnt++; rep(i,1,M) if(b[i]) cnt++; x=res; } double dfs(ll Now,int D) { Change(Now); int num=cnt,d[13]; rep(i,1,N+M) d[i]=c[i]; if(mp.find(Now)!=mp.end()) return mp[Now]; if(Now<FCY) return mp[Now]=1.0; if(D==0) return mp[Now]=0.0; double res=0; rep(i,1,N+M) { if(d[i]==0) continue; d[i]--; if(d[i]==0) num--; res+=dfs(Now-P[i-1],D-1)/(num+(d[i]==0)); if(d[i]==0) num++; d[i]++; } return mp[Now]=res; } int main() { scanf("%d%d%d",&N,&M,&K); rep(i,1,N) scanf("%d",&a[i]),sum+=a[i]; rep(i,1,M) scanf("%d",&b[i]),sum+=b[i]; if(K>=sum) return puts("1.00000000"),0; ll Now=0; FCY=1; P[0]=1; cnt=N+M; rep(i,1,N+M) P[i]=P[i-1]*10; rep(i,1,M) Now=Now*10+b[i],c[N+M+1-i]=b[i]; rep(i,1,N) Now=Now*10+a[i],FCY*=10,c[N+1-i]=a[i]; printf("%.8lf ",dfs(Now,K)); return 0; }
H .House Lawn
by 许
#include<bits/stdc++.h> #define db double #define ll long long using namespace std; const int maxn=1e6+6,inf=1e9; char str[1005]; struct node { char s[65]; int id,p; bool operator<(const node&t)const { if(p==t.p)return id<t.id; return p<t.p; } }a[105]; void gao(int cur,int &pri,int &c,int &t,int &r) { int n=strlen(str),i=0; pri=c=t=r=0; while(str[i]!=',')i++; i++; while(str[i]!=',') pri=pri*10+str[i++]-'0';i++; while(str[i]!=',') c=c*10+str[i++]-'0';i++; while(str[i]!=',') t=t*10+str[i++]-'0';i++; while(i<n) r=r*10+str[i++]-'0'; } int main() { int e,m,pri,c,t,r,v,n=10080,cnt=0; cin>>e>>m; getchar(); for(int i=1;i<=m;i++) { gets(str); gao(i,pri,c,t,r); v=n/(t+r)*t*c; if(v<e) { int tmp=n%(t+r); db v1=(db(e)-v)/c,v2=tmp-v1; if(v1<=(db)t) if(v1*r<=v2*t)v=e; } if(v>=e) { a[++cnt].p=pri; a[cnt].id=i; int len=strlen(str),j=0; while(str[j]!=',') a[cnt].s[j]=str[j],j++; a[cnt].s[j]='