3.22-3.23学习总结

E - Pots https://vjudge.net/contest/547627#problem/E

思路:

  1. 求最少操作用bfs
  2. 一共6种操作,操作后,俩容器的状态会发生改变
  3. 用一个book[i][j]数组表示第一个容器装了 i 的水,第二个容器装了 j 的水
  4. 用一个结构体表示俩容器的状态以及变成这种状态的步骤
  5. 对于某个状态,去搜索6种操作,将操作后的状态入队,同时标记该状态,下次不再访问

队空时,输出impossible

代码

#include
#include
#include
using namespace std;
bool book[101][101];
int a,b,c;
struct state{
	int i;
	int j;
	int op[10000];
	int step;
}t;
queueque;

bool bfs()
{
	while(!que.empty())
	{
		t=que.front();
		if(t.i==c||t.j==c)
		{
			printf("%d\n",t.step);
			for(int j=1;j<=t.step;j++)
			{
				if(t.op[j]==1)
				{
					printf("FILL(1)\n");
				}
				else if(t.op[j]==2)
				{
					printf("FILL(2)\n");
				}
				else if(t.op[j]==3)
				{
					printf("DROP(1)\n");
				}
				else if(t.op[j]==4)
				{
					printf("DROP(2)\n");
				}
				else if(t.op[j]==5)
				{
					printf("POUR(1,2)\n");
				}	
				else if(t.op[j]==6)
				{
					printf("POUR(2,1)\n");
				}																				         
			}
			return true;
		}
		for(int i=1;i<=6;i++)
		{
			state temp=t;
			if(i==1&&book[a][t.j]==false&&t.i!=a)//装满a容器
			{
				temp.i=a;
				temp.j=t.j;
				temp.step=t.step+1;
				temp.op[temp.step]=1;
				que.push(temp);
				book[a][t.j]=true;
			} 
			else if(i==2&&book[t.i][b]==false&&t.j!=b)//装满b容器
			{
				temp.i=t.i;
				temp.j=b;
				temp.step=t.step+1;
				temp.op[temp.step]=2;
				que.push(temp);
				book[t.i][b]=true;
			}
			else if(i==3&&book[0][t.j]==false&&t.i!=0)//drop a容器
			{
				temp.i=0;
				temp.j=t.j;
				temp.step=t.step+1;
				temp.op[temp.step]=3;
				que.push(temp);
				book[0][t.j]=true;
			}
			else if(i==4&&book[t.i][0]==false&&t.j!=0)//drop b容器
			{
				temp.i=t.i;
				temp.j=0;
				temp.step=t.step+1;
				temp.op[temp.step]=4;
				que.push(temp);
				book[t.i][0]=true;				
			}	
			else if(i==5&&t.i!=0)//pour a容器->b
			{
				if(t.i>b-t.j&&book[t.i+t.j-b][b]==false)//倒满有剩余
				{
					temp.i=t.i+t.j-b;
					temp.j=b;
					temp.step=t.step+1;
					temp.op[temp.step]=5;
					que.push(temp);
					book[t.i+t.j-b][b]=true;
				}
				if(t.i<=b-t.j&&book[0][t.j+t.i]==false)//全部倒过去
				{
					temp.i=0;
					temp.j=t.j+t.i;
					temp.step=t.step+1;
					temp.op[temp.step]=5;
					que.push(temp);
					book[0][t.j+t.i]=true;
				}
			}
			else if(i==6&&t.j!=0)//pour b容器->a
			{
				if(t.j>a-t.i&&book[a][t.j+t.i-a]==false)//倒满有剩余
				{
					temp.i=a;
					temp.j=t.j+t.i-a;
					temp.step=t.step+1;
					temp.op[temp.step]=6;
					que.push(temp);
					book[a][t.j+t.i-a]=true;
				}
				if(t.j<=a-t.i&&book[t.j+t.i][0]==false)//全部倒过去
				{
					temp.i=t.j+t.i;
					temp.j=0;
					temp.step=t.step+1;
					temp.op[temp.step]=6;
					que.push(temp);
					book[t.j+t.i][0]=true;
				}
			}								
		}
		que.pop();
	}
	return false;
}

int main()
{
	scanf("%d%d%d",&a,&b,&c);
	book[0][0]=true;
	t.i=0;t.j=0;t.step=0;
	que.push(t);
	if(bfs()==false) printf("impossible\n");	
	return 0;
}

P - Beat https://vjudge.net/contest/547627#problem/P

思路:

  1. 使用dfs+回溯,在所有情况里面找最大值
  2. 从第一行开始搜索,时间大于刚解决的,可以搜索,并标记,防止重复解决这个问题。然后进入该问题所对应的行,再次搜索

代码

#include
#include
int book[20];
int prob[20][20];
int n;
int ans;
int temp;
void dfs(int p,int t)
{
	if(temp>ans) ans=temp;
	for(int i=0;i=t&&book[i]==0)
		{
			book[i]=1;
			temp++;
			dfs(i,prob[p][i]);
			temp--;
			book[i]=0;
		}
	}
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{		
		for(int i=0;i

 Q - 生日蛋糕 https://vjudge.net/contest/547627#problem/Q

思路:

  1. 在所有可能的R和H中找最小面积S,dfs+减枝
  2. 判断第一层R和H的范围,由于最上面那层的R和H最小为1,所以第一层的R和H最小为M;假设只有第一层蛋糕,体积一定,R最小为M,所以H一定小于N/(M*M);H最小为M,所以R一定小于sqrt(N/M)。
  3. 其他层数i,Ri->(M-i,Ri-1-1),H同理
  4. 如果到最上面那一层,体积仍然没有凑到N,return
  5. 如果体积和大于N,return
  6. 对于i层后,它们的体积最大值一定小于Ri*Ri*Hi,如果当前体积加上这个值仍然小于或等于N,return
  7. 对于i层后剩余n体积,它们的最小面积一定大于 2*n/Ri ,如果当前面积加上这个值大于等于s,return

 代码

#include 
#include 
#include
using namespace std;
int N,M;
int minn=999999999;
int ans=minn;
void dfs(int i,int n,int m,int s,int rl,int hl)//剩余层数为m,剩余体积为n, 前i层的面积
{ 
	if(m==0&&n==0&&s=ans) return;//目前面积+之后最小体积大于ans
	for(int r=m;r<=rl-1;r++)
	{
		for(int h=m;h<=hl-1;h++)
		{			
			dfs(i+1,n-r*r*h,m-1,s+2*r*h,r,h);
		}
	}
}

int main()
{
	scanf("%d%d",&N,&M);
	//dfs(1,N,M)
	for(int r=M;r*r<=N/M;r++)//将体积全给第一层,求出r的大致范围
	{
		for(int h=M;h<=N/(M*M);h++)
		{
			dfs(2,N-r*r*h,M-1,r*r+2*r*h,r,h);
		}
	}
	if(ans==minn) printf("0\n");
	else printf("%d\n",ans);
    return 0;
}

面向对象

1.认识

2.class与instance

3.对象的内存布局

3.22-3.23学习总结_第1张图片

 3.22-3.23学习总结_第2张图片

 

你可能感兴趣的:(java学习,学习)