会场预约
找一个最小的r加进集合1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <cstdio>
#include <algorithm>
#include<iostream>
#define maxn 1000000
#include<set>
using namespace std;
int n;
struct node{
int s,t;
bool operator<(const node &v)const{
if(t==v.t)
return s<v.s;
return t<v.t;
}
};
set <node> c;
int main()
{
scanf("%d",&n); set<node>::iterator w;
for(int i=1;i<=n;i++)
{
char b;int s,t;
cin>>b;
if(b=='A')
{
scanf("%d%d",&s,&t);
int cnt=0;
while(1){
w=c.lower_bound((node){0,s});
if(w!=c.end()&&t>=w->s)
{
c.erase(w);
cnt++;
continue;
}
c.insert((node){s,t});
break;
}
printf("%d\n",cnt);
}
else printf("%d\n",c.size());
}
}
油滴扩展
这个题很恶心啊。。
精度处理太tm恶心了。。。。。。。。。。。
思路:
因为n<=6,这也太小了
直接求出全排列来,求出所有点之间的距离,这个点扩展的距离就等于到已确定的点的距离-它的半径的最小值,然后一点点模拟。。
距离小于之前的半径了,就把他的半径付为零,我因这wa曾了四个点1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const double p=3.1415926535;
double xx,x2,yy,y2,x[19999],y[19999];
bool ff[3000];
int n;
double w[199999],f[1999][1999],minn=9999999999;
int b[199999];
double jl(double x,double y,double z,double w){
double xxx=x-z;
double yyy=y-w;
return (double)sqrt(xxx*xxx+yyy*yyy);
}
double min(double x,double y)
{
return x<y?x:y;
}
double abs2(double x)
{
return x>=0?x:-x;
}
void dfs(int ww){
if(ww==n+1)
{
memset(w,127,sizeof(w));
for(int i=1;i<=n;i++)
{
w[b[i]]=min(abs2(x[b[i]]-(double)x2),abs2((double)xx-x[b[i]]));
w[b[i]]=min(abs2(y[b[i]]-(double)y2),w[b[i]]);w[b[i]]=min(abs2((double)yy-y[b[i]]),w[b[i]]);
for(int j=1;j<i;j++)
{
w[b[i]]=min(w[b[i]],f[b[i]][b[j]]-w[b[j]]);
if(w[b[i]]<0)w[b[i]]=0;
}
}
double www=(double)abs(xx-x2)*abs(yy-y2);
for(int i=1;i<=n;i++)
{
//printf("%lf ",w[b[i]]);
www-=w[b[i]]*w[b[i]]*p;
}
minn=min(minn,www);
return ;
}
for(int i=1;i<=n;i++)
{
if(!ff[i])
{
b[ww]=i;
ff[i]=1;
dfs(ww+1);
ff[i]=0;
}
}
}
int main()
{
scanf("%d",&n);
scanf("%lf%lf%lf%lf",&x2,&y2,&xx,&yy);
for(int i=1;i<=n;i++)
scanf("%lf%lf",&x[i],&y[i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=j)
{
f[i][j]=jl(x[i],y[i],x[j],y[j]);
}
}
dfs(1);
printf("%d",int(minn+0.5));
return 0;
}
引水入城
疯狂爆搜233333
dfsdfs%%%%
许多大佬都用bfs判断,这里我用了dfs,就不用再写bfs了。
思路
很容易发现区间一定是连续的,否则不行,就可以先爆搜出区间左和右,转化为一个区间覆盖问题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,ans;
struct st{
int l,r;
}s[1999];
int cmp(const st &a,const st &b)
{
if(a.l<b.l||a.l==b.r&&a.r<b.r)return 1;
return 0;
}
int a[1999][1999],f[1999][1999],q[1999][1999],ff[19999];
int xx[4]={1,-1,0,0},yy[4]={0,0,1,-1},maxn=0;
int dfs(int w,int x,int y)
{
if(x==n)
{
s[w].l=min(s[w].l,y);s[w].r=max(s[w].r,y);
}
for(int i=0;i<=2;i++)
{
int xxx=x+xx[i];
int yyy=y+yy[i];
if(xxx<1||xxx>n||yyy<1||yyy>m) continue;
if(a[xxx][yyy]<a[x][y]&&!q[xxx][yyy])
{
q[xxx][yyy]=1;
dfs(w,xxx,yyy);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(int i=1;i<=m;i++)
if(a[1][i]>=a[1][i-1]&&a[1][i]>=a[1][i+1])
{
q[1][i]=1;
dfs(i,1,i);
}
for(int i=1;i<=m;i++)
if(!q[n][i]) ans++;
if(ans) {
printf("0\n%d",ans);
return 0;
}
else {
for(int i=1;i<=m;i++)
s[i].l=999999999,s[i].r=0;
for(int i=1;i<=m;i++)
if(a[1][i]>=a[1][i-1]&&a[1][i]>=a[1][i+1])
{
memset(q,0,sizeof(q));
q[1][i]=1;
dfs(i,1,i);
}
sort(s+1,s+m+1,cmp);
int i=m;while(s[i].l==999999999)i--;
int tot=0;
while(maxn<m){
int wwww=maxn;
for(int j=1;j<=i;j++){
if(s[j].l<=maxn+1)
wwww=max(s[j].r,wwww);
}
tot++;
maxn=wwww;
}
printf("1\n%d",tot);
}
}
小木棍
爆搜,我觉得我的应该更优,可不行,不知为什么,就看了题解
加了剪枝
1.如果不行,比他大的也不行。
2.如果第一个不行剩下的都不行
3.相同的不行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63#include<cstdio>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
int cmp(const int a,const int b)
{
return a>b;
}
int n,s,x[1999],vis[1999],maxn,ans,i,tot;
int dfs(int w,int q,int p){
if(p==tot)
{
return 1;
}
if(w==0)
{
if(dfs(i,1,p+1)) return 1; ;
}
for(int j=q;j<=n;j++)
{
if(!vis[j]&&x[j]<=w)
{
vis[j]=1;
if(dfs(w-x[j],j+1,p))return 1;
vis[j]=0;
if(w==x[j]||w==i) break;
while(x[j+1]==x[j])j++;
}
}
return 0;
}
int main()
{
scanf("%d",&n);
for(int j=1;j<=n;j++)
{
scanf("%d",&x[j]);
if(x[j]<=50)
{
maxn=max(maxn,x[j]);
s+=x[j];
}
else n--,j--;
}
sort(x+1,x+n+1,cmp);
for(i=maxn;i<=s;i++)
if(s%i==0)
{
tot=s/i;
if(dfs(i,1,0))
{
printf("%d",i);
return 0;
}
}
}
八数码难题
调了一下午终于ac了,恶心死我了23333333
这个题大佬们都是用什么康托展开,什么hash。。。
作为一个懒。。我不想写了,就写了个bool,暴力判断重的情况
可是九维的bool会爆数组啊,那我们就要想一个问题,因为数码不会重,知道了前八位,最后一位可以推出来,这样就不会爆了,就可以尽情的去爆搜了
我用了一个bfs
思路:先取出一个0,从0开时搜,交换值
交换值时打一个表就很好解决了1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74#include<cstdio>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
struct st{
int s;
int l;
int ans;
};
bool ss[88888888];int n;
int mb=123804765;
int p[9]={100000000,10000000,1000000,100000,10000,1000,100,10,1};
int xx[9]={-1,3,-3,1};
queue <st> q;
int bfs(){
ss[n/10]=1;
while(!q.empty())
{
st x = q.front();
if(x.s == mb) {
printf("%d",x.ans);
return 1;
}
q.pop();
for(int i=0;i<=3;i++)
{
int x2=x.l+xx[i];
int j=x.l;
if(x2<0||x2>8) continue;
if(j%3==2&&xx[i]==1) continue;
if(j%3==0&&xx[i]==-1) continue;
int w=(x.s/p[x2])%10;
int www=(x.s/p[j]+w)*p[j]+x.s%p[j];
www=www/p[x2]/10*10*p[x2]+www%p[x2];
if(!ss[www/10])
{
// printf("%d %d\n",www,x.ans+1);
ss[www/10]=1;
st o;o.s=www;o.l=x2;o.ans=x.ans+1;
q.push(o);
}
}
}
}
int main()
{
scanf("%d",&n);
int ww=n,t=8;
while(ww){
if(ww%10==0)
break;
t--;
ww/=10;
}
st o;
o.s=n; o.l=t;o.ans=0;
q.push(o);
bfs();
return 0;
}
虫食算
这个题很6啊
字符串处理很恶心啊,在我调了两个晚自习之后终于a了
思路:枚举每一个数字代表哪一个字母,如果是30分,就是一个全排列啊,找出所有排列前情况,暴力判断是否过
而这样显然,26的阶乘会炸的很惨,所以我们就需要很多优化
1.如果一竖行的都算出来了,直接判断是否正确,就不用枚举下面的了
2.如果第一位的加起来大于等于n了,就要进位了,这是不符合题意的
3.按从后往前的的顺序搜,先枚举最后的,一排一排的枚举,找出一个序列,这样可以使1优化和更优1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<stdlib.h>
using namespace std;
int n,ff[999];
int z[999], b[399];char w[399];
char a[399],c[399];int pos[999],cnt,s[999];
int add()
{
memset(z,0,sizeof(z));
for(int i=n-1;i>=0;i--)
{
z[i]+=b[a[i]-'A']+b[c[i]-'A'];
z[i-1]+=z[i]/n;
z[i]%=n;
}
for(int i=0;i<n;i++)
if(z[i]!=b[w[i]-'A']) return 0;
return 1;
}
bool check1()
{
for(int i=n-1;i>=0;i--)
if(b[a[i]-'A']!=-1&&b[c[i]-'A']!=-1&&b[w[i]-'A']!=-1)
if(((b[a[i]-'A']+b[c[i]-'A'])%n!=b[w[i]-'A'])&&((b[a[i]-'A']+b[c[i]-'A']+1)%n!=b[w[i]-'A']))
return 0;
return 1;
}
void dfs(int ww){
if(b[a[0]-'A']+b[c[0]-'A']>n-1)return ;
if(!check1())return ;
if(ww==n)
{
if(add())
{
for(int i=0;i<n;i++)
printf("%d ",b[i]);
exit(0);
}
return ;
}
for(int i=n-1;i>=0;i--)
{
if(!ff[i])
{
b[pos[ww]]=i;
ff[i]=1;
dfs(ww+1);
ff[i]=0;
b[pos[ww]]=-1;
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<=n;i++) b[i]=-1;
for(int i=0;i<n;i++)cin>>a[i]; for(int i=0;i<n;i++)cin>>c[i]; for(int i=0;i<n;i++)cin>>w[i];
for(int i=n-1;i>=0;i--){
if(!s[a[i]-'A'])
{
pos[cnt++]=a[i]-'A';
s[a[i]-'A']=1;
}
if(!s[c[i]-'A'])
{
pos[cnt++]=c[i]-'A';
s[c[i]-'A']=1;
}
if(!s[w[i]-'A'])
{
pos[cnt++]=w[i]-'A';
s[w[i]-'A']=1;
}
if(cnt==n)break;
}
dfs(0);
return 0;
}
mayan游戏
这个题是个大爆搜。。。
考虑把一个位置的方块移到右面,就等同于把一个方块移到左面,所以只枚举向右的就行了,可以保证优先级,但这个位置的方块如果是空的,虽然是向右移的,但题目不让这么输出,所以打个标记就行了。
所以我们的思路就出来了,先枚举换的位置,如果相同就不用换,然后交换,清除,使空中的快下降,
下降完后一次次清除,一次次下降,直到不行为止,这样的话不会超时吗,因为n只有5啊,所以不会爆。
1 | #include<cstdio> |