显幻闪过的ACMspace

 
 

Powered by: 博客园
模板提供:沪江博客
博客园 | 首页 | 发新随笔 | 发新文章 | 联系 | 订阅订阅 | 管理

2010年2月27日

寒假完了,总结一下

寒假回家还是学了很多知识的,巩固了之前自己一直不常熟练的图论的一些算法,搜索算法,最短路算法和生成树算法,感觉还是有很大的收获,但是发现一些问题,首先,自己对于数据结构上的问题还是很生疏,例如处理大规模的图结构的时候对于邻接表的书写还是很陌生,需要学习的地方,还有就是很多算法的优化都要用到数据结构中的知识,所以回到学校要赶快学习数据结构的了。第二,虽然自己书写算法的思路有一定的清晰度了,但是对于代码的长度却很纠结,一个STL的BFS居然都能写到4000B+,不晓得是怎么回事的了,多看看别人的代码,看看别人是怎么提高代码的效率的。回到学校了以后,除了学习数据结构以外,补上关于求前连通分量,图匹配的问题。图论想先放一放的了,多看看书,有空的时候切切题,下学期空闲的时候比较多,应该可以切多点题的吧。

回学校前的最后一晚上写了一道题,又是4000B+。。。。MST+PRIM(POJ3026)同化所有的外星人,看成一堆人去同化外星人,同化了外星人后分开去同化其他的外星人,就是求所有节点的MST的权值。自己的代码跑了43MS,应该还可以得到优化,在求解DIS数组的时候,可以降低复杂度,毕竟这个矩阵是个对称阵的,剩下自己也没想的了,加上一个判断就可以解决的了。

 

代码
//MST+BFS 要是不看DISSCUSS 估计又是WA。。。


#include
<iostream>
#include
<queue>
using namespace std ;

typedef 
struct node_p{
      
int x0 , y0 , step ;
}node ;

const int maxn = 55 ;
const int maxm = 105 ;
const int INF = 1000000000 ;

char temp[10000] ;
int map[maxn][maxn] , dis[maxm][maxm] , d[maxm] , d_flag[maxm] ;
int x , y ; //x__col y__row
node cur_node ,de_node;
int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};

void BFS( int cur_x , int cur_y ,int count ){
      
int p_num , flag[maxn][maxn] ;
      queue
<node>q ;
      memset(flag , 
0 , sizeof(flag)) ;
      p_num 
= 0 ;
      
      cur_node.x0 
=  cur_x ;
      cur_node.y0 
=  cur_y ;
      cur_node.step 
= 0 ;
      flag[cur_x][cur_y] 
= 1 ;
      q.push(cur_node) ; 
// start-point pushed

        
while(!q.empty()){
             cur_node 
= q.front() ;
             q.pop() ;
            
             
/*printf("cur_node.x0 == %d ",cur_node.x0);
             printf("cur_node.y0 == %d ",cur_node.y0);
             printf("cur_node.step == %d\n ",cur_node.step);
*/
  
             
if( map[cur_node.x0][cur_node.y0] != 0 && map[cur_node.x0][cur_node.y0] != -1 ){
                 dis[map[cur_x][cur_y]][map[cur_node.x0][cur_node.y0]] 
= cur_node.step ;
                 dis[map[cur_node.x0][cur_node.y0]][map[cur_x][cur_y]] 
= cur_node.step ;
                 p_num 
++ ;
                 
if(count == p_num)
                    
break ;
             }
              
//update
                for( int i = 0 ; i < 4 ; i++ ){
                    
int px , py ;
                    px 
= cur_node.x0 + dir[i][0] ;
                    py 
= cur_node.y0 + dir[i][1] ;
                    
if(flag[px][py] == 0
                        
&& px>=0 && px<y
                        
&& py>=0 && py<x
                        
&& map[px][py] != 0 ){
                             de_node.x0 
= px ;
                             de_node.y0 
= py ;
                             de_node.step 
= cur_node.step + 1 ;
                             flag[px][py] 
= 1 ;
                             q.push(de_node) ;
                    }
                }
         }
}
        

int main(){
      
int T , i , j , count ;
      scanf(
"%d",&T) ;
  
      
while( T-- ){
          scanf(
"%d%d",&x,&y) ;
          gets(temp) ;  
//for useless space_char
          memset(map , 0 , sizeof(map)) ;
          memset(d_flag , 
0 , sizeof(d_flag)) ;
          count 
= 0 ;

          
for( i = 0 ; i < y ; i++ ){
             gets(temp);
             
for( j = 0 ; j < x ; j++ ){
                
if(temp[j] == '#')
                    map[i][j] 
= 0 ;
                
else if(temp[j] == ' ')
                      map[i][j] 
= -1 ;
                
else if(temp[j] == 'A'||temp[j] == 'S'){
                      count 
++ ;
                      map[i][j] 
= count  ;
                     }
              }
          }

           
//BFS to get_dis
             for( i = 0 ; i < count ; i++ ){
               
for( j = 0 ; j < count ; j++ ){
                   dis[i][j] 
= INF ;
               }
             }
             
for( i = 0 ; i < y ; i++ ){
               
for( j = 0 ; j < x ; j++){
                  
if(map[i][j] != 0 && map[i][j] != -1 )
                     BFS(i , j , count) ;
               }
             }
            
//debug..
             /*for( i = 1 ; i <= count ; i++ ){
                 for( j = 1 ; j <= count ; j++ ){
                      printf("%d ", dis[i][j]);
                 }
                 printf("\n");
             }
*/
  
           
//prim to get MST_ans ;
              int ans ;
              ans 
= 0 ;
              d_flag[
1] = 1 ;
            
              
for( i = 1 ; i <= count ; i++ )
                  d[i] 
= dis[1][i] ;
     
              
for( i = 2 ; i <= count ; i++ ){
                  
int min_node = 0 ;
                  
int minlen = INF ;
                  
for( j = 1 ; j <= count ; j++ ){
                     
if( minlen > d[j] && d_flag[j] == 0 ){
                         min_node 
= j ;
                         minlen 
= d[j] ;
                     }
                  }
                   
if(min_node != 0 ){
                       
//printf("minlen = %d\n",minlen) ;
                       d_flag[min_node] = 1 ;
                       ans 
+= minlen ;
                       
//printf("ans = %d\n" , ans) ;
                       for( j = 1 ; j <= count ; j++ ){
                           
if(d[j]>dis[min_node][j])
                              d[j] 
= dis[min_node][j] ;
                       }
                   }
                   
else break ;
               }
   printf(
"%d\n",ans) ;
 }
return 0;
} 

 

 

posted @ 2010-02-27 02:04 Jpretty 阅读(35) 评论(0) 编辑
 

2009年10月4日

POJ 1012 约瑟夫问题 打表,好邪恶。
在市里面的呢。。旁边又没IDE。。看了这道题。。打表法。这个是DISCUSS的算法的哦,不是原创,不过学习约瑟夫环问题,顺便学习链表数据结构。看后续的文章的了。
PS:打表好邪恶。。。其实很多的题在数据不大的情况下可以先本地打表,然后再过。。。好邪恶。。
#include<iostream>

using namespace std;


int array[14]={2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,13482720};

int main()
{
	int k;
	cin>>k;
	while(k!=0)
	{
		cout<<array[k-1]<<endl;
		cin>>k;
	}
	return 0;
}
posted @ 2009-10-04 23:55 Jpretty 阅读(438) 评论(0) 编辑
 

2009年9月21日

PKU 1067 取石子游戏
威佐夫博弈(Wythoff Game)
这个是完全的博弈论的知识然后只要参考知识写出代码就可以的了。

有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10).可以看出,a0=b0=0,ak是未在前面出现过的最小自然数,而 bk=ak+k.

    那么任给一个局势(a,b),怎样判断它是不是奇异局势呢?我们有如下公式:

    ak =[k(1+√5)/2],bk= ak + k  (k=0,1,2,...,n 方括号表示取整函数)

奇妙的是其中出现了黄金分割数(1+√5)/2 = 1。618...,因此,由ak,bk组成的矩形近似为黄金矩形,由于2/(1+√5)=(√5-1)/2,可以先求出j=[a(√5-1)/2],若a=[j(1+√5)/2],那么a = aj,bj = aj + j,若不等于,那么a = aj+1,bj+1 = aj+1+ j + 1,若都不是,那么就不是奇异局势。然后再按照上述法则进行,一定会遇到奇异局势。

#include<stdio.h>
int main()
{ int n,m,swap;
  int k;
  double r=0.6180339887,R=1/r;
   while(scanf("%d%d",&a,&b)==2)
    {  if(n>m){ swap=n;
                       n=m;m=swap;}
              k=n*r;
            if(n!=(int)(k*R))
                 ++k;
            printf("%d\n",m!=(int)(k*R)+k);
    }

return 0;
}


 

posted @ 2009-09-21 22:58 Jpretty 阅读(536) 评论(0) 编辑
 
PKU 2348
博弈问题,代码量很少的呢,不过题目中间的思想才是重点的。

#include<stdio.h>
int count;
void match(int a,int b)
{ int swap;
  if(a<b){ swap=a;
           a=b;
           b=swap;
         }
  if(a==b) return;    //如果两组数相等,那么面对这个局势的人获胜
  if(a/b>=2)  return;    //如果面对此局势,是必胜的,代码后有注解
  else {count++;
     match(a-b,b);

  }
}


int main()
{ int a,b;
  while(scanf("%d%d",&a,&b)!=EOF)
  { if(a==0&&b==0)
       return 0;
    count=0;    //这个是定义了如果每个人都采用PREFECT的战略的话,到达这个必胜的局面时经过的轮数
     match(a,b);
  //printf("count==%d\n",count);
    if(count%2)      //如果是奇数轮的话那么后拿的那个人获胜
        printf("Ollie wins\n");
    else
     printf("Stan wins\n");
   }
 return 0;
}

a/b>=2,面对这个局势的时候,a=b*k+q,那么可以看做a是由k堆b再加上q组成的,那么如果取走全部的K堆的时候得到的如果是必败的战略,那么面对这个局势的人获胜,如果取走全部的K堆得到的是必胜的战略,那么这个人完全可以取走k-1堆b,让接下来的这个人去面对这个必败局势,所以这个情况也是。所以这道题就没问题的了。
posted @ 2009-09-21 22:30 Jpretty 阅读(86) 评论(0) 编辑
 

2009年9月12日

电一的ACM自学成才组成立的了。。。。。
自己发觉一个人搞这些真的很难的呢,而且在我们学院的,搞ACM的人很少的说,没事得,多发展点人来搞,大家都是新手的额,多个人可以多问下,多讨论,也不会觉得很孤单地了嘛。。。。。希望这个组织能搞下去,为了参加大二下的校赛的目标。改天去问问砾哥看他有时间的没哎,要是有的话把他拖来给我们讲,嘿嘿。。。。。要是没时间就算了的哦。。。
今天A了一道水题,很简单的,代码就不贴的了,现在做这样的DFS题有心得的了呢,三段,main,begin,DFS,直接出结果。
自己的大学到底是为了什么的呢,不能天天宅宿舍的了。。。每周初星期四以外的所有的晚上都要上晚自习的了。。。。星期四是CODING时间。。。。~~
posted @ 2009-09-12 23:03 Jpretty 阅读(63) 评论(2) 编辑
 

2009年9月2日

PKU 1020 Anniversary Cake
#include<iostream>
using namespace std;
int cake[11],pos[41];              //题目限制的是蛋糕的最大变长为10,且需分割的最大边长为40
int m,k;

bool DFS(int a)                        
{ 
int i,min_pos=41,lie=0,j,t;
  
if(a==k)                        //如果遍历到放入的数目和要求的数目相同即完成目标
    return true;
  
for(i=1;i<=m;i++)
    
if(pos[i]<min_pos){
       min_pos
=pos[i];           //找到了在竖直方向上用去的最短行数
       lie=i;
       }
  
for(i=10;i>=1;i--){
    
if(cake[i]&&min_pos+i<=m&&lie+i-1<=m){             //可以放入边长为I的正方形
       for(j=lie;j<=lie+i-1;j++)
          
if(pos[j]>min_pos)                      //该空隙的宽度大于等于i
             break;                                     
        
if(j>lie+i-1){
           cake[i]
--;                               //这个就是典型的DFS算法的了
           for(t=lie;t<=lie+i-1;t++)
                pos[t]
=pos[t]+i;
           
if(DFS(a+1))
                
return true;  //I GET THE WA HERE
           cake[i]++;                              //回溯部分的算法
           for(t=lie;t<=lie+i-1;t++)
                pos[t]
=pos[t]-i;
           }
    }
  }
return false;
}

int main()
{ 
int n,sum_cake,ori_cake,i,s;         //sum_cake为要做的蛋糕的总面积,ori_cake为给的蛋糕的总面积
  scanf("%d",&n);
  
while(n--){
     memset(cake,
0,sizeof(cake));
      memset(pos,
0,sizeof(pos));
     scanf(
"%d%d",&m,&k);
     sum_cake
=0;
     ori_cake
=m*m;
     
for(i=1;i<=k;i++){
       scanf(
"%d",&s);
       cake[s]
++;
       sum_cake
=sum_cake+s*s;
      }
     
//printf("sum_cake==%d,ori_cake==%d\n",sum_cake,ori_cake);
     if(sum_cake!=ori_cake)
       printf(
"HUTUTU!\n");
     
else
       
if(DFS(0)) printf("KHOOOOB!\n");
       
else printf("HUTUTU!\n");
     }
return 0;
}

//感觉挺好的一道题,DFS部分用得很经典,关键部分是找到放正方形的策略,每次寻找到单行的最短行数,由大的开始放
//还有没有其他的方法的呢,这种做法始终让人不是很放心,这样的放置方式可以任一情况下都行吗?
posted @ 2009-09-02 00:22 Jpretty 阅读(418) 评论(0) 编辑
 

2009年8月31日

PKU 3256 cowpicnic
摘要: [代码]联系BFS。。居然写出了一段DFS代码。。。。明天写下这道题的BFS的吧。。比较下算法。。。400MS过,悲哀呢。。。阅读全文
posted @ 2009-08-31 23:51 Jpretty 阅读(45) 评论(2) 编辑
 

2009年8月30日

POJ 3126 Prim Path
摘要: #include<stdio.h>#include<string.h>int n1, n2; bool prim[10000]; int value[10000]; int q[11000]; int c[4]= {1, 10, 100, 1000};void prime(){ int i,j; prim[0]=prim[1]=false; for(i=2;i<500...阅读全文
posted @ 2009-08-30 21:55 Jpretty 阅读(195) 评论(0) 编辑
 

2009年8月28日

POJ 3051 Satellite Photographs
摘要: 还是DFS。。。。真好用的呢。。开这么大的规模的数组时间都不超过150MS。。。。。125MS过。可以剪枝的吗,觉得找不到剪枝的地方的呢。[代码]在家里的最后一道题的了,很简单的一道题的呢,对DFS有比较初步的理解的了,砾哥说还有维护一个栈的DFS写法。。回学校了再研究的吧。回学校了开始入门BFS,一样一样来的嘛,不着急。。PS:这个农场可够大的。。。。。阅读全文
posted @ 2009-08-28 16:30 Jpretty 阅读(204) 评论(0) 编辑
 
POJ 2627 sUDOKU
摘要: 这道题的思路不是很难的吧,也是DFS就可以解决的,不过输入的时候为什么要用字符串输入的呢,不懂,但是我用SCANF就不行的嘛,还是纠结的,看了DISCUSS,过了,但1426MS,代码就不贴了嘛,据说有反着搜的方法,去看看再说的。用数组来表示当前组什么数字用过的是能节约时间的了。for(i=1;i<=9;i++) for(j=1;j<=9;j++){ soduku[i][j] = c[...阅读全文
posted @ 2009-08-28 15:07 Jpretty 阅读(43) 评论(0) 编辑
 
仅列出标题  下一页