2018.7.5 模拟赛
这次比赛再一次确认了我是瞎子的事实。。。。。
盲人。
T1,一道曾经讲过的原题,忘了原来做法,写了个二分+spfa。结果手残打出了以下代码
if(c>='a' && c<='z') x=c-70,city[x]=2;
if(s>='a' && s<='z') y=s-70,city[x]=2;
两个x真的是棒,结果样例还过了????手造数据还过了?????假的吧。
这种错误不只一次犯了, 以后每次写完代码一定要检查,养成好习惯。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const int MAXN = 3005;
int n,p,sum,S,T,ans,num;
int head[MAXN],cnt;
int to[MAXN<<1],nxt[MAXN<<1];
int city[MAXN],dis[MAXN];
bool vis[MAXN];
inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
inline bool check(int x){
memset(vis,0,sizeof(vis));
memset(dis,-1,sizeof(dis));
queue<int> q;
q.push(S);vis[S]=1;dis[S]=x;
while(q.size()){
int xx=q.front();q.pop();
vis[xx]=0;
for(register int i=head[xx];i;i=nxt[i]){
int u=to[i];
if(city[u]==1){
int now=0;
now=dis[xx]/20;
if(now*20<dis[xx]) now++;
// if(dis[xx]-now<x) continue;
if(dis[u]<dis[xx]-now){
dis[u]=dis[xx]-now;
if(!vis[u]) {
vis[u]=1;
q.push(u);
}
}
}
else{
if(dis[u]<dis[xx]-1){
// if(dis[xx]-1<x) continue;
dis[u]=dis[xx]-1;
if(!vis[u])
vis[u]=1;
q.push(u);
}
}
// if(u==T) return true;
}
}
if(dis[T]>=sum) return true;
return false;
}
int main(){
freopen("toll.in","r",stdin);
freopen("toll.out","w",stdout);
while(~scanf("%d",&n)){
num++;
if(n==-1) break;
ans=0;cnt=0;
memset(head,0,sizeof(head));
memset(city,0,sizeof(city));
for(register int i=1;i<=n;i++){
char c,s;
int x,y;
cin>>c>>s;
if(c>='A' && c<='Z') x=c-'A'+1,city[x]=1;
if(s>='A' && s<='Z') y=s-'A'+1,city[y]=1;
if(c>='a' && c<='z') x=c-70,city[x]=2;
if(s>='a' && s<='z') y=s-70,city[y]=2;
add(x,y);add(y,x);
// cout<<x<<" "<<y<<endl;
}
char c,s;
scanf("%d",&sum);
cin>>c>>s;
if(c>='A' && c<='Z') S=c-'A'+1;
if(s>='A' && s<='Z') T=s-'A'+1;
if(c>='a' && c<='z') S=c-70;
if(s>='a' && s<='z') T=s-70;
int l=sum,r=100000000;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) {
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
printf("Case %d: %d\n",num,ans);
}
return 0;
}
T2看了半天题,结果没看懂,自己yy了一道题来做???并查集,我是来搞笑的。
正解结果是一个lis,虽然看出了点门道没多想。爆零GG。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 100005;
int n;
int a[MAXN],dp[MAXN];
int top;
int main(){
freopen("sort.in","r",stdin);
freopen("sort.out","w",stdout);
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
for(register int i=1;i<=n;i++) {
if(dp[top]<a[i]) dp[++top]=a[i];
else dp[lower_bound(dp+1,dp+1+top,a[i])-dp]=a[i];
}
printf("%d",top);
}
T3 刚开始写状压,后面认为自己状压太丑就写了一发爆搜+剪枝。一个最优性剪枝是记录下来后面还能打开的最大的钥匙的量,如果加上现在的还是小于答案就直接跳。结果。。。刚开始错误的一个剪枝没删干净?????还给了60????
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int MAXN = 20;
int n,A,B,C;
int ans,ret;
bool vis[MAXN];
struct Door{
int use[5],sum,key[5];
}door[MAXN];
//inline bool cmp(Door A,Door B){
// return A.sum<B.sum;
//}
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
return x*f;
}
inline void dfs(int u,int x,int y,int z){
if(x+y+z>ans) ans=x+y+z;
if(x+y+z+ret<=ans) return;
// if(x+y+z<door[u].sum) return;
// if(u==n+1) return;
for(register int i=1;i<=n;i++){
if(vis[i]) continue;
if(x>=door[i].use[1] && y>=door[i].use[2]){
vis[i]=1;
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret+door[i].sum-door[i].key[2]-door[i].key[1]-door[i].key[3];
dfs(i,x-door[i].use[1]+door[i].key[1],y-door[i].use[2]+door[i].key[2],z+door[i].key[3]);
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret-door[i].sum+door[i].key[2]+door[i].key[1]+door[i].key[3];
vis[i]=0;
}
if(x>=door[i].use[1] && y<door[i].use[2] && y+z>=door[i].use[2]){
vis[i]=1;
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret+door[i].sum-door[i].key[2]-door[i].key[1]-door[i].key[3];
dfs(i,x-door[i].use[1]+door[i].key[1],door[i].key[2],z-(door[i].use[2]-y)+door[i].key[3]);
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret-door[i].sum+door[i].key[2]+door[i].key[1]+door[i].key[3];
vis[i]=0;
}
if(y>=door[i].use[2] && x<door[i].use[1] && x+z>=door[i].use[1]){
vis[i]=1;
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret+door[i].sum-door[i].key[2]-door[i].key[1]-door[i].key[3];
dfs(i,door[i].key[1],y-door[i].use[2]+door[i].key[2],z-(door[i].use[1]-x)+door[i].key[3]);
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret-door[i].sum+door[i].key[2]+door[i].key[1]+door[i].key[3];
vis[i]=0;
}
if(y<door[i].use[2] && x<door[i].use[1] && (x+y+z)>=door[i].sum){
vis[i]=1;
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret+door[i].sum-door[i].key[2]-door[i].key[1]-door[i].key[3];
dfs(i,door[i].key[1],door[i].key[2],x+y+z-door[i].sum+door[i].key[3]);
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret=ret-door[i].sum+door[i].key[2]+door[i].key[1]+door[i].key[3];
vis[i]=0;
}
// dfs(i,x,y,z);
// vis[i]=0;
}
}
int main(){
freopen("room.in","r",stdin);
freopen("room.out","w",stdout);
n=rd();
for(register int i=1;i<=n;i++) door[i].use[1]=rd();
for(register int i=1;i<=n;i++) door[i].use[2]=rd();
for(register int i=1;i<=n;i++) door[i].key[1]=rd();
for(register int i=1;i<=n;i++) door[i].key[2]=rd();
for(register int i=1;i<=n;i++) door[i].key[3]=rd();
A=rd();B=rd();C=rd();
for(register int i=1;i<=n;i++)
door[i].sum=door[i].use[1]+door[i].use[2];
// cout<<ret<<endl;
// sort(door+1,door+1+n,cmp);
// for(register int i=1;i<=n;i++) cout<<door[i].sum<<" ";
// cout<<endl;
// cout<<ret<<endl;
// for(register int i=2;i<=n;i++)
// ret[i]=ret[i-1]+door[i-1].sum-door[i-1].key[1]-door[i-1].key[2]-door[i-1].key[3];
// for(register int i=1;i<=n;i++)
// cout<<ret[i]<<" ";
// cout<<endl;
for(register int i=1;i<=n;i++)
if(door[i].key[1]+door[i].key[2]+door[i].key[3]>door[i].sum)
ret+=door[i].key[1]+door[i].key[2]+door[i].key[3]-door[i].sum;
dfs(1,A,B,C);
printf("%d",ans);
return 0;
}
总结:
这次考试真的的是菜成狗,首要问题是治眼瞎和脑残,以后写完代码都要检查一遍,都要自己造数据争取1A。。好的,就这样吧。