怎么说呢,算是找到了短板吧。
虽然炸得有点惨,不过接下来一段时间怕是没心情再摸鱼了QAQ
DAY1
分析
都说是一道结论题,如果在考场上直接证不出来,可以先编几组数据找找规律,然后反证,用反证法就简单多了。
值得注意的一点就是要开long long
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long a,b;
scanf("%lld%lld",&a,&b);
printf("%lld\n",a*b-a-b);
return 0;
}
分析
一道大模拟,没太多好说的,只是要注意特殊情况,尤其是嵌套
在考的时候,满心以为自己又A了一道题,结果崩到只有20分——大小写,是No而不是NO,我该感谢上苍我还有20分……
当时下来后,我发现了这个事实后瞬间心态爆炸
知我者谓我心忧,不知我者谓我何求,悠悠苍天,此何人哉! QAQ
这道题其实数据有点水 ,比如这样的代码,本来是错的,但也过了(只给了核心代码):
int t,lcl[30];
struct ff
{
int o,var;
};
void work()
{
while(t--)
{
mem(lcl);
int lenth,f=1,np,mp=0,p1=0;
char c=' ',pc='E';
stack<ff>s;
read(lenth);
if(lenth&1) f=2;
read(np);
if(np==1) np=0;
else read(np);
for(int i=1;i<=lenth;++i){
c=getchar();
while(c!='E'&&c!='F') c=getchar();
if(c=='F') {
if(pc=='E') p1=0;
c=getchar();
c=getchar();
int y=c-'a',u,v; ff x;
if(lcl[y]) f=2;
lcl[y]=1; x.var=y;
read(u);read(v);
if(u>v) x.o=-1;
else if(u==300) x.o=0;
else if(v==300) x.o=1;
else x.o=0;
s.push(x); pc='F';
}
else
{
if(s.empty()) f=2;
else
{
ff x=s.top();
s.pop();
if(x.o==-1)
{
if(pc=='E') p1=0;
}
else
if(pc=='E') p1+=x.o;
else p1=Max(p1,x.o);
if(s.empty())
{
mp=Max(mp,p1);
p1=0;
}
pc='E'; lcl[x.var]=0;
}
}
}
if(!s.empty()) f=2;
if(mp!=np&&f!=2) f=0;
if(f==1) printf("Yes\n");
else if(f==2) printf("ERR\n");
else printf("No\n");
}
}
这代码错就错在没有存下内里并列嵌套循环的最大时间复杂度,而是直接用了最后嵌套的循环当作最大,它是过不了这组数据:
1
12 O(n^4)
F a 1 n
F b 1 n
F c 1 n
F d 1 n
E
E
E
F e 1 n
F f 1 n
E
E
E
正确应输出Yes,这个错误程序输出的是No,不过洛谷与这次考试的数据中应该都没有这样的数据……
下面放正确代码:
(当然有大佬比我写的好看多了也快多了)
代码
/*
User:Mandy.H.Y
Problem:D1T2
Language:c++
*/
#include<bits/stdc++.h>
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)>(y)?(x):(y)
#define mem(A) memset((A),0,sizeof(A))
using namespace std;
const int maxn=0;
int t;
int lcl[30]; //小写字母的标记
struct ff{ //o-这个语句的时间复杂度 var-这个语句的变量
int o,var,prc,oz; //prc-这条语句上一个符号('E'或'F')
}; //oz-这个循环里面嵌的循环的最大复杂度
template<typename T>inline void read(T &x)//读入优化
{
x=0;char c=getchar();bool f=0;
while((c<'0'||c>'9')&&c!='n') {f|=(c=='-');c=getchar();}//如果读到n了,需要特判
if(c=='n') {c=getchar(); x=300; return;} //若读到n,则返回一个大于100的数,方便判断
while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48); c=getchar();}
if(f)x=-x;
}
template<typename T>void putch(const T x)//输出优化
{
if(x>9) putch(x/10);
putchar((x%10)|48);
}
template<typename T>void put(const T x)
{
if(x<0) putchar('-'),putch(-x);
else putch(x);
}
void docu()
{
freopen("1.txt","r",stdin);
}
void readdata()
{
read(t);
}
void work()
{
while(t--)
{
mem(lcl);
int lenth,p1=0,mp=0,np=0,f=1;//lenth-这个程序的长度 p1-当前循环(无嵌套)的时间复杂度
char c,pc='E'; //mp-这个程序的最大复杂度 np-给出的时间复杂度
//pc-上一行开始的字母 //f-用于判断,f==0:No f==1:Yes f==2:ERR
stack<ff>s;//栈用于存循环语句
read(lenth);
if(lenth&1) f=2;//若长度是奇数,则F与E一定不匹配
read(np);//读入给出的时间复杂度
if(np==1) np=0;
else read(np);
for(int i=1;i<=lenth;++i)
{
c=getchar();
while(c!='E'&&c!='F') c=getchar();//用while读掉回车、空格
if(c=='F')
{
if(pc=='E')
{
if(!s.empty())//维护oz值
{
ff z=s.top();
s.pop();
z.oz=Max(z.oz,p1);
s.push(z);
}
p1=0;
}
c=getchar();
c=getchar();
int y=c-'a',u,v;
ff x;
if(lcl[y]) f=2;//标记变量
lcl[y]=1; x.var=y;
read(u);read(v);
if(u>v) x.o=-1;//计算这条语句的时间复杂度
else if(u==v||v<300) x.o=0;
else x.o=1;
x.prc=pc;//后续操作
x.oz=0;
s.push(x);
pc='F';
}
else
{
if(s.empty()) f=2;
else
{
ff x=s.top(); s.pop();
lcl[x.var]=0;//清除标记
p1=Max(p1,x.oz);//维护p1
if(x.o==-1) p1=0;
else if(pc=='F') p1=x.o;
else p1+=x.o;
if(s.empty())//维护mp
{
mp=Max(mp,p1);
p1=0;
}
else if(x.prc=='E')//维护oz,主要是嵌套中的最后一个
{
ff z=s.top(); s.pop();
z.oz=Max(z.oz,p1);
s.push(z);
p1=0;
}
pc='E';//后续操作
}
}
}
if(!s.empty()) f=2;//有F无E
if(f!=2&&mp!=np) f=0;//保证语法正确后,判断时间复杂度是否计算正确
if(f==1) printf("Yes\n");//注意大小写!!!!!!!
else if(f==2) printf("ERR\n");
else printf("No\n");
}
}
int main()
{
// docu();
readdata();
work();
return 0;
}
原谅我个蒟蒻+懒人还没调出来……
DAY 2
分析
方法一:深搜+染色(似乎比并查集还快那么一丢丢)
方法二:并查集
还有一点,记得开 long long 不然要爆,特别是算距离的时候
最后,注意精度,不用开根号,直接平方就行,保证精度
代码
- 深搜+染色
/*
User:Mandy.H.Y
Language:c++
Problem:cheese
*/
#include<bits/stdc++.h>
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define mem(A) memset((A),0,sizeof(A))
using namespace std;
const int maxn=1005;
struct zuobiao
{
int x,y,z;
}che[maxn];
typedef long long ll;
int t,n,h,r;
bool vis[maxn];
template<typename T>inline void read(T &x)
{
x=0;char c=getchar();bool f=0;
while(c<'0'||c>'9') {f|=(c=='-');c=getchar();}
while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f)x=-x;
}
template<typename T>void putch(const T x)
{
if(x>9) putch(x/10);
putchar((x%10)|48);
}
template<typename T>inline void put(const T x)
{
if(x<0) putchar('-'),putch(-x);
else putch(x);
}
void docu()
{
freopen("cheese.txt","r",stdin);
}
void readdata()
{
read(t);
}
bool dfs(int u)
{
if(che[u].z+r>=h) return true;
vis[u]=1;
ll x1=(ll)che[u].x,yy=(ll)che[u].y,z1=(ll)che[u].z;
long long r2=(ll)r+r;
for(int i=1;i<=n;++i)
{
ll x2=(ll)che[i].x,y2=(ll)che[i].y,z2=(ll)che[i].z;
if(che[i].z>che[u].z+r2) break;
if(i==u||vis[i]) continue;
if(che[i].z<che[u].z-r2) continue;
ll dis=(x1-x2)*(x1-x2)+(yy-y2)*(yy-y2)+(z1-z2)*(z1-z2);
if(dis<=r2*r2)
{
if(dfs(i)) return true;
}
}
return 0;
}
bool cmp(zuobiao a,zuobiao b)
{
return a.z<b.z;
}
void work()
{
while(t--)
{
bool judge=0;
mem(vis);
read(n);read(h);read(r);
for(int i=1;i<=n;++i)
{
read(che[i].x);
read(che[i].y);
read(che[i].z);
}
sort(che+1,che+n+1,cmp);//排个序,方便剪枝
int i=1;
while(che[i].z>=-r&&che[i].z<=r)
{
if(i>n) break;
if(vis[i])
{
++i;
continue;
}
if(dfs(i))
{
judge=1;
break;
}
++i;
}
if(judge) printf("Yes\n");
else printf("No\n");
}
}
int main()
{
// docu();
readdata();
work();
return 0;
}
- 并查集
#include<bits/stdc++.h>
using namespace std;
int t,h,f[1005],n,r,p[1005],num=0,w=0;
void init()
{
freopen("2.txt","r",stdin);
}
void readdata()
{
scanf("%d",&t);
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
void meger(int x,int y)
{
f[find(y)]=find(x);
}
void work()
{
for(int g=1;g<=t;g++)
{
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
num=0;
long long x[1002],y[1002],z[1002];
scanf("%d%d%d",&n,&h,&r);
for(int i=1;i<=n;i++)
{
f[i]=i;
scanf("%lld%lld%lld",&x[i],&y[i],&z[i]);
if(z[i]<=r) f[i]=0;
if(z[i]+r>=h)
{
num++;
p[num]=i;
}
for(int j=1;j<i;j++)//这里不需要判断,因为必须一个一个地判距离,一个一个地枚举,不能一棒打死一个集合
{
long long d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])+(z[i]-z[j])*(z[i]-z[j]);
if(4*(long long)r*r>=d)//注意long long,一般遇到这种,直接全声明成long long,
{
if(find(i)==0) meger(f[i],f[j]);
else meger(f[j],f[i]);
}
}
}
w=0;
for(int i=1;i<=num;i++)
{
if(find(p[i])==0)
{
printf("Yes\n");
w=1;
break;
}
}
if(w==0)
printf("No\n");//输出时注意!!
}
}
int main()
{
//init();
readdata();
work();
return 0;
}
分析
作为一个深搜渣渣,我光荣的爆零了 (其实是我没有交程序)
我说过,我可是搜索要腾飞的人,搜索与我的决斗就在这个寒假
当然不是搜索被我征服就是我把搜索征服
这道题有很多方法,目前我打了一种,其他方法持续更新……
代码
/*
User:Mandy.H.Y
Language:c++
Problem:treasure
*/
#include<bits/stdc++.h>
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)<(y)?(x):(y)
#define mem(A) memset((A),0,sizeof(A))
#define mem1(A) memset((A),0x3f3f3f3f,sizeof(A))//注意0x3f3f3f3f
using namespace std;
const int maxn=13;
const int maxm=1005;
int n,m,size=0,ans;
int first[maxn],dep[maxn],fee[8200],edge[maxn][maxn];
template<typename T>inline void read(T &x)
{
x=0;char c=getchar();bool f=0;
while(c<'0'||c>'9') {f|=(c=='-');c=getchar();}
while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
if(f)x=-x;
}
template<typename T>void putch(const T x)
{
if(x>9) putch(x/10);
putchar((x%10)|48);
}
template<typename T>inline void put(const T x)
{
if(x<0) putchar('-'),putch(-x);
else putch(x);
}
void docu()
{
freopen("treasure.txt","r",stdin);
}
void readdata()
{
read(n);
read(m);
mem1(edge);
for(int i=1;i<=m;++i)
{
int x,y,z;
read(x);read(y);read(z);
edge[x][y]=Min(edge[x][y],z);
edge[y][x]=edge[x][y];
}
}
void dfs(int S)
{
for(int i=1;i<=n;++i)
{//i是走过的点
if((1<<(i-1))&S)
{
for(int j=1;j<=n;++j)
{
int S1=1<<(j-1);
if(!(S&S1)&&edge[i][j]!=0x3f3f3f3f)
{//j未走过
//i可以走到j
int fee1=fee[S]+dep[i]*edge[i][j];
if(fee[S|S1]>fee1)
{//当前状态的总费用可更新
fee[S|S1]=fee1;
dep[j]=dep[i]+1;
dfs(S|S1);
dep[j]=0x3f3f3f3f;
}
}
}
}
}
}
void work()
{
ans=0x3f3f3f3f;
mem1(dep);
for(int i=1;i<=n;++i)
{
mem1(fee);
int S=1<<(i-1);
dep[i]=1;
fee[S]=0;
dfs(S);
dep[i]=0x3f3f3f3f;
ans=Min(ans,fee[(1<<n)-1]);//!!!!!!!
}
put(ans);
}
int main()
{
// docu();
readdata();
work();
return 0;
}
懒人持续更新中……