zoukankan      html  css  js  c++  java
  • 倒水问题(Fill,UVA 10603) lrj白书 p202

    看着lrj的代码自己敲了一遍,还没调试成功。。。。

    有时间再进行完善

     /*
     状态start到各个状态u1,u2,u3.....
     的倒水量分别为u1.dist,u2.dist,u3.dist....
     */
     /*
     按倒水量递增的顺序去寻找当前状态的v[0],v[1],v[2]是否为d
     但是程序实现的时候我们寻找目标水量是根据 ans[d]>0,而不是对每一个状态的v[]进行遍历
     为什么这样做呢?当然是因为麻烦,ans[d]>0很直接地说明了v[]有三者之一为d
     */
     #include <cstdio>
     #include <cstring>
     #include <queue>
     using namespace std;
    
     struct Node{
    	 int v[3],dist;
    	 bool operator <(const Node &u) const{
    		 return dist >u.dist;
       }
     };
    
    
     const int maxn=200+5;
     int vis[maxn][maxn],cap[3],ans[maxn];//因为只有三只杯子,所以记录前两只杯子的状态即可
     void update_ans(const Node &u){
    	 for (int i=0;i<3;i++){
    		 int d=u.v[i];
    	 if(ans[d]<0||u.dist<ans[d]) ans[d]=u.dist;//每次有新的状态时,记录形成d升水所需要的最小倒水量
    	 }
     }
     void solve(int a,int b,int c,int d){
    	 cap[0]=a;
    	 cap[1]=b;
    	 cap[2]=c;
    	 memset(vis,0,sizeof(vis));//vis[]记录三元组状态是否重复
    	 memset(ans,-1,sizeof(ans));//ans[]记录当前的最小倒水量
    	 priority_queue<Node> q;
    
    	 Node start;
    	 start.dist=0;//总的倒水量
    	 start.v[0]=0;start.v[1]=0;start.v[2]=c;
    	 q.push(start);//准备工作
    
    	 vis[0][0]=1;//设置初始状态为已访问
    	 /*!当所有状态都被访问完,就算ans[d]<0,while{}也停止
    	 !!当ans[d]>0,表示输出所求的状态已找到,停止循环*/
    	 while (!q.empty()){
    		 Node u=q.top();q.pop();//对优先队列表头(即当前队列结点.dist最小)的结点进行访问
    		 update_ans(u);
    		 if (ans[d]>=0)  break;
    		 //从v[i]--v[j]加水,加多少水呢?只要能加,就加到不能加为止
    		 for(int i=0;i<3;i++)
    			 for(int j=0;j<3;j++)if(i!=j){
    				 if(u.v[i]==0||u.v[j]==cap[j]) continue; //过渡到下一个i或下一个j
    				 int amount=min(cap[j],u.v[i])-u.v[j];
    				 Node u2;
    				 memcpy(&u2,&u,sizeof(u));
    				 u2.dist=u.dist+amount;
    				 u2.v[i]-=amount;
    				 u2.v[j]+=amount;
    				 if (!vis[u2.v[0]][u2.v[1]]){
    					 vis[u2.v[0]][u2.v[1]]=1;
    					 q.push(u2);
    				 }
    			 }
    	 }
    
    	 while (d>=0){
    		 if(ans[d]>=0){
    			 printf("%d %d
    ",ans[d],d);
    			 return;
    		 }
    		 d--;
    	 }
     }
    
     int main(){
    	 int T,a,b,c,d;
    	 scanf("d%",&T);
    	 while(T--){
    		 scanf("%d%d%d%d",&a,&b,&c,&d);
    		 solve(a,b,c,d);
    	 }
    	 return 0;
     }
    

      

    认准了,就去做,不跟风,不动摇
  • 相关阅读:
    Session共享的解决方案[转]
    学习SAS_001_循环语句中读取数据文件
    如何让远程数据库中的1张表导入到本地数据库中
    SAS之COMPBL、DEQUOTE函数
    使用winzip命令行对文件打包压缩
    让每个单词的第一个字母自动大写
    For the distance calculation
    SAS数据集转置
    Web开发/设计人员应当知道的15个网站
    你从没见过的 HTML5 动画效果
  • 原文地址:https://www.cnblogs.com/mdz-great-world/p/6375437.html
Copyright © 2011-2022 走看看