算法
解题思路
使用dfs,对蛋糕每层可能的高度和半径进行穷举.通过观察我们可以知道第一层的圆面积是它上面所有蛋糕层的圆面积之和,所以我们只要去求每层的侧面积就行了.
因为题目要求Ri > Ri+1且Hi > Hi+1,所以我们可以求出每层的最小体积和侧面积,用两个数组分别储存起来.
然后进入dfs我们从最上层开始对每层的高度和半径进行穷举,要注意的是这道题有很多的剪枝要做不然就会超时.
剪枝1:如果接下来每一层都按照最小的来算,依然大于了总体积则可以剪去.
剪枝2:如果接下来每一层都按照最小的来算,结果已经大于了求出的最优值,可以剪去.
剪枝3:通过变形公式,如果接下来的体积用完所需的最小表面积已经大于了最优值,可以剪去.
然后我们在穷举到最后一层的时候用一个变量来记录最小的面积就好了.
代码
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
int n,m;
int sv[35];
int st[35];
int min1=2147483647;
int dfs(int deep,int v,int s,int lr,int lh)
{
if(deep==0)
{
if(v==n&&min1>s)
min1=s;
return 0;
}
if(v+sv[deep-1]>n)
return 0;
if(s+st[deep-1]>min1)
return 0;
if(s+2*(n-v)/lr>=min1)
return 0;
for(int i=lr-1;i>=deep;i--)
{
if(deep==m)
{
s=i*i;
}
int h=min(lh-1,(n-v-sv[deep-1])/(i*i));
for(;h>=deep;h--)
{
dfs(deep-1,v+i*i*h,s+2*i*h,i,h);
}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int x=1;x<=m;x++)
{
sv[x]=sv[x-1]+x*x*x;
st[x]=st[x-1]+x*x*2;
}
dfs(m,0,0,n,n);
if(min1==2147483647)
min1=0;
printf("%d",min1);
return 0;
}
解题思路
这道题我们用bfs来求逃出迷宫的最短时间.这道题目不同的点在于它多了对应的钥匙和门,并且有的时候还会走回头路.
经过观察可以发现只有找到新的钥匙后走回头路才有意义,所以我们要将钥匙的状态保存下来,这里我们要用到位运算符:&和|.
他们都是在二进制的基础上进行运算的.
&:只有当对应位置都为一运算结果才为一.举例:010&110=010.
|:只有当对应位置都为零运算结果才为一.举例:010|110=110.
了解了这两个位运算符我们就可以用一个值来表示钥匙状态了,我们只要在碰见钥匙时用 '|' 将对应的一加上去,碰到门时用 '&' 判断是否有钥匙就行了.
要注意的是当点所用的时间超过规定时间时就不进入队列.
代码
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
char g[25][25];
int j[25][25][1030];
int ne[5][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct ss
{
int x;
int y;
int k;
int t;
}d[650000];
int l,r;
int n,m,t;
int bfs()
{
ss a;
while(l<r)
{
for(int x=0;x<4;x++)
{
a.x=d[l].x+ne[x][0];
a.y=d[l].y+ne[x][1];
a.k=d[l].k;
a.t=d[l].t;
if(a.x<0||a.y<0||a.x>=n||a.y>=m)
continue;
if(g[a.x][a.y]!='*'&&j[a.x][a.y][a.k]!=1)
{
if(g[a.x][a.y]=='.'||g[a.x][a.y]=='@')
{
a.t++;
if(a.t>=t)
return -1;
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}
if(g[a.x][a.y]=='^')
{
a.t++;
if(a.t>=t)
return -1;
return a.t;
}
if(g[a.x][a.y]>='a'&&g[a.x][a.y]<='z')
{
a.t++;
if(a.t>=t)
return -1;
a.k=a.k|(1<<(g[a.x][a.y]-'a'));
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}
if(g[a.x][a.y]>='A'&&g[a.x][a.y]<='Z')
{if(a.k&(1<<(g[a.x][a.y]-'A')))
{
a.t++;
if(a.t>=t)
return -1;
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}}
}
}
l++;
}
return -1;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&t))
{
memset(j,0,sizeof(int )*25*25*1030);
l=r=0;
for(int x=0;x<n;x++)
{
scanf("%s",g[x]);
}
for(int x=0;x<n;x++)
{
for(int y=0;y<m;y++)
{
if(g[x][y]=='@')
{
d[r].x=x;
d[r].y=y;
d[r].t=0;
d[r++].k=0;
j[x][y][0]=1;
}
}
}
printf("%d\n",bfs());
}
return 0;
}
类似的题
解题思路
这道题目与上面的题非常相像只是在进行位运算是有所不同,进行一点小小的处理就行了.
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
char g[100][100];
int j[100][100][100];
int ne[5][2]={{1,0},{-1,0},{0,1},{0,-1}};
struct ss
{
int x;
int y;
int k;
int t;
}d[650000];
int l,r;
int n,m,t;
int bfs()
{
ss a;
while(l<r)
{
for(int x=0;x<4;x++)
{
a.x=d[l].x+ne[x][0];
a.y=d[l].y+ne[x][1];
a.k=d[l].k;
a.t=d[l].t;
if(a.x<0||a.y<0||a.x>=n||a.y>=m)
continue;
if(g[a.x][a.y]!='#'&&j[a.x][a.y][a.k]!=1)
{
if(g[a.x][a.y]=='.'||g[a.x][a.y]=='*')
{
a.t++;
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}
if(g[a.x][a.y]=='X')
{
a.t++;
return a.t;
}
if(g[a.x][a.y]>='a'&&g[a.x][a.y]<='z')
{
a.t++;
int p;
switch(g[a.x][a.y])
{
case 'b':p=1;break;
case 'y':p=2;break;
case 'r':p=3;break;
case 'g':p=4;break;
}
if(a.k|(1<<p))
a.k=a.k|(1<<p);
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}
if(g[a.x][a.y]>='A'&&g[a.x][a.y]<='Z')
{
int p;
switch(g[a.x][a.y])
{
case 'B':p=1;break;
case 'Y':p=2;break;
case 'R':p=3;break;
case 'G':p=4;break;
}
if(a.k&(1<<p))
{
a.t++;
d[r].x=a.x;
d[r].y=a.y;
d[r].t=a.t;
d[r++].k=a.k;
j[a.x][a.y][a.k]=1;
}
}
}
}
l++;
}
return -1;
}
int main()
{
while(1)
{
scanf("%d%d",&n,&m);
if(n==0&&m==0)
break;
memset(j,0,sizeof(int )*100*100*100);
l=r=0;
for(int x=0;x<n;x++)
{
scanf("%s",g[x]);
}
for(int x=0;x<n;x++)
{
for(int y=0;y<m;y++)
{
if(g[x][y]=='*')
{
d[r].x=x;
d[r].y=y;
d[r].t=0;
d[r++].k=0;
j[x][y][0]=1;
}
}
}
int p;
p=bfs();
if(p==-1)
{
printf("The poor student is trapped!\n",p);
}
else
{
printf("Escape possible in %d steps.\n",p);
}
}
return 0;
}
java知识学习
多态(补充)
通过这两天对多态的学习,我学会了多态的一些知识,所以在此补充.
多态的弊端是无法调用子类特有的方法,只能调用父类和子类共有的方法,这时我们可以通过强制转换然后赋值给另一个子类的对象来调用子类特有的方法.
public class person {
private String name;
private int age;
public person() {
}
public person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println(name+","+age);
}
}
public class student extends person {
@Override
public void show() {
System.out.println("学生的信息:"+getName()+","+getAge());
}
public void play(){
System.out.println("子类的特有方法");
}
}
以上是两个类,它们两个是继承关系person是student的父类.
public class Main {
public static void main(String[] args) {
person a=new student();
a.setAge(18);
a.setName("张三");
a.show();
a.play();
}
}
当如此调用这两个类时,会报错,无法使用子类特有的play方法
当我们使用强制转换后就可以使用
public class Main {
public static void main(String[] args) {
person a=new student();
a.setAge(18);
a.setName("张三");
a.show();
student b=(student) a;
b.play();
}
}
运行结果
注意:考虑到当数据量变大时无法记住谁是谁的父类时,进行强制类型转换时可能出现异常,因此进行类型转换之前应先通过instanceof运算符来判断是否可以成功转换.
运算符:instanceof
instanceof 运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以 是接口,可以把接口理解成一种特殊的类),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回 false。
在使用 instanceof 运算符时需要注意: instanceof 运算符前面操作数的编译时类型要么与后面的类相 同,要么与后面的类具有父子继承关系,否则会引起编译错误.
使用方法
student b=new student();
if(a instanceof student==true)
{
b=(student)a;
}
总结
这个周末学习java的时间有点短,学习的有点慢需要加快速度