2017北京国庆刷题Day7 morning
期望得分:100+0+100=200
实际得分:100+20+0=120
离散化搞搞
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 100001 int a[N],b[N]; bool vis[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int main() { freopen("del.in","r",stdin); freopen("del.out","w",stdout); int n,k; read(n); read(k); for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i]; sort(b+1,b+n+1); int tot=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tot+1,a[i])-b; int cnt1=0,cnt2=0; for(int i=1;i<=n;i++) if(!vis[a[i]]) vis[a[i]]=true,cnt1++; else cnt2++; if(k<=cnt2) printf("%d\n",cnt1); else printf("%d\n",cnt1-(k-cnt2)); return 0; }
阅读理解之坑:加冕没有用
出题人想表达停在那儿,就是不再继续跳吃
考场上没写出来原因有二:
1、死磕加冕
2、怕TLE,写的记忆化,这种题最好先打出裸的dfs
#include<cstdio> #include<algorithm> using namespace std; char s[11]; int mp[11][11]; bool mp2[11][11],vis[11][11]; int cnt,mx,tot; struct node { int x,y; }ans[101]; int dx[4]={-1,-1,1,1}; int dy[4]={-1,1,1,-1}; void init() { for(int i=1;i<=10;i++) { scanf("%s",s+1); for(int j=1;j<=10;j++) mp[i][j]=s[j]-'0'; } for(int i=1;i<=10;i++) { scanf("%s",s+1); for(int j=1;j<=10;j++) mp2[i][j]=s[j]-'0'; } } bool inmap(int x,int y) { return (!(x<=0) && !(x>10) && !(y<=0) && !(y>10)); } bool empty(int x,int y) { return !mp[x][y]; } bool jump(int x,int y) { if(!inmap(x,y)) return false; return mp[x][y]==2; } bool have(int x,int y) { return vis[x][y]; } void update(int i,int j) { if(cnt>mx) { mx=cnt; tot=1; ans[1].x=i; ans[1].y=j; } else if(cnt==mx) { ans[++tot].x=i; ans[tot].y=j; } } void dfs(int x,int y,int sx,int sy) { vis[x][y]=true; for(int i=0;i<4;i++) if(jump(x+dx[i],y+dy[i]) && inmap(x+dx[i]+dx[i],y+dy[i]+dy[i]) && empty(x+dx[i]+dx[i],y+dy[i]+dy[i])) { if(have(x+dx[i],y+dy[i]) || have(x+dx[i]+dx[i],y+dy[i]+dy[i]) ) continue; cnt++; update(sx,sy); dfs(x+dx[i]+dx[i],y+dy[i]+dy[i],sx,sy); cnt--; } vis[x][y]=false; } void dfs2(int x,int y,int sx,int sy) { vis[x][y]=true; for(int d=0;d<4;d++) { int nx=x,ny=y; for(int i=1;i<=10;i++) { nx+=dx[d]; ny+=dy[d]; if(!inmap(nx,ny)) break; if(mp[nx][ny]==1) break; if(!jump(nx,ny)) continue; if(have(nx,ny)) continue; vis[nx][ny]=true; int nnx=nx,nny=ny; for(int j=1;j<=10;j++) { nnx+=dx[d]; nny+=dy[d]; if(!inmap(nnx,nny)) break; if(!empty(nnx,nny)) break; if(have(nnx,nny)) continue; cnt++; update(sx,sy); dfs2(nnx,nny,sx,sy); cnt--; } vis[nx][ny]=false; } } vis[x][y]=false; } void solve() { for(int i=1;i<=10;i++) for(int j=1;j<=10;j++) if(mp[i][j]==1) { if(!mp2[i][j]) dfs(i,j,i,j); else dfs2(i,j,i,j); } if(!mx) { cnt=1; for(int i=1;i<=10;i++) for(int j=1;j<=10;j++) if(mp[i][j]==1) { if(!mp2[i][j]) { for(int k=0;k<2;k++) if(inmap(i+dx[k],j+dy[k]) && empty(i+dx[k],j+dy[k])) update(i,j); } else { for(int k=0;k<4;k++) { int nx=i,ny=j; for(int l=1;l<=10;l++) { nx+=dx[k];ny+=dy[k]; if(!inmap(nx,ny)) break; if(!empty(nx,ny)) break; update(i,j); } } } } } printf("%d\n",tot); for(int i=1;i<=tot;i++) printf("(%d,%d)\n",ans[i].x,ans[i].y); } int main() { freopen("chess.in","r",stdin); freopen("chess.out","w",stdout); init(); solve(); }
考场上顺退概率DP+拓扑排序,全WA了。。
正解倒推
dp[i][j]表示还有i个馅饼没有掉下来,当前还差状态为j的馅饼的期望美味度
(还差状态为j的馅饼指的是 还有状态为j的馅饼没有吃到)
枚举当前要掉哪类馅饼
如果能吃,那就从吃和不吃里选最优解
如果不能吃,那就直接又后面转移
所以 状态转移方程(设当前正掉下第l类的馅饼)
if((j&pre[l])==pre[l]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|(1<<l-1)]+val[l]);
else dp[i][j]+=dp[i+1][j];
因为是期望,不要忘了除n
最后应该输出dp[0][0]
代码中因为是从n开始枚举的,所以输出了dp[1][0]
(感谢cyz020202 指出)
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define K 101 #define N 16 int bit[N]; int val[N],pre[N]; double dp[K+1][1<<N+1]; void read(int &x) { x=0; int f=1; char c=getchar(); while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } x*=f; } int main() { freopen("bonus.in", "r", stdin); freopen("bonus.out", "w", stdout); int k,n,x; read(k); read(n); bit[0]=1; for(int i=1;i<=n;i++) bit[i]=bit[i-1]<<1; for(int i=1;i<=n;i++) { read(val[i]); read(x); while(x) pre[i]+=bit[x-1],read(x); } int S=1<<n; for(int i=k;i;i--) for(int j=0;j<S;j++) { for(int l=1;l<=n;l++) if((j&pre[l])==pre[l]) dp[i][j]+=max(dp[i+1][j],dp[i+1][j|bit[l-1]]+val[l]); else dp[i][j]+=dp[i+1][j]; dp[i][j]/=1.0*n; } printf("%.6lf",dp[1][0]); }