青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

M.J的blog

algorithm,ACM-ICPC
隨筆 - 39, 文章 - 11, 評(píng)論 - 20, 引用 - 0
數(shù)據(jù)加載中……

此blog廢掉啦~

       請(qǐng)?jiān)L問http://www.orzminjie.info/

posted @ 2010-12-08 22:59 M.J 閱讀(266) | 評(píng)論 (0)編輯 收藏

求樹的直徑

              樹的直徑是指樹的最長(zhǎng)簡(jiǎn)單路。求法: 兩遍BFS :先任選一個(gè)起點(diǎn)BFS找到最長(zhǎng)路的終點(diǎn),再?gòu)慕K點(diǎn)進(jìn)行BFS,則第二次BFS找到的最長(zhǎng)路即為樹的直徑;
              原理: 設(shè)起點(diǎn)為u,第一次BFS找到的終點(diǎn)v一定是樹的直徑的一個(gè)端點(diǎn)
              證明: 1) 如果u 是直徑上的點(diǎn),則v顯然是直徑的終點(diǎn)(因?yàn)槿绻鹶不是的話,則必定存在另一個(gè)點(diǎn)w使得u到w的距離更長(zhǎng),則于BFS找到了v矛盾)
                      2) 如果u不是直徑上的點(diǎn),則u到v必然于樹的直徑相交(反證),那么交點(diǎn)到v 必然就是直徑的后半段了
                       所以v一定是直徑的一個(gè)端點(diǎn),所以從v進(jìn)行BFS得到的一定是直徑長(zhǎng)度

              相關(guān)題目有TOJ1056,TOJ3517.

TOJ 1056(Labyrinth):
        大意是一個(gè)由‘#’和'.'構(gòu)成的迷宮,'.'表示可行,‘#’表示不可行,問可行的最長(zhǎng)的路的長(zhǎng)度是多少。

#include <cstdio>
#include 
<cstring>
#include 
<queue>
#define M 1002

using namespace std;

int r,c;
char map[M][M];
bool flag[M][M];
int move[4][2]={-1,0,1,0,0,-1,0,1};                                               // 分別表示上下左右
int maxt;
struct Node{
        
int x,y,num;
};
Node ans;
bool legal(int x,int y){                                                                   //判斷該點(diǎn)是否越界及是否可走
        if(x >=0 && x < r && y>=0 && y < c &&map[x][y]=='.'return true;
        
return false;
}
void bfs(Node start){
        memset(flag,
false,sizeof(flag));                                               //初始所有點(diǎn)標(biāo)記為false
        flag[start.x][start.y] = true;                                                    //起點(diǎn)標(biāo)記為true
        queue<Node>f;
        
while(!f.empty()) f.pop();                                                       //清空創(chuàng)建的隊(duì)列
        Node m,n,tep;
        
int tx,ty,xx,yy;
        
int i,j,k,num;
        f.push(start);
        
while(!f.empty()){                                                                   //如果隊(duì)列不為空
                m = f.front();                                                                   //取出隊(duì)首元素
                tx = m.x; ty = m.y; num = m.num;
                
if(num > maxt){                                                              //如果該元素的長(zhǎng)度大于maxt,更新maxt
                        maxt = num;
                        ans 
= m;
                }
                
for(i = 0;i < 4; i++){                                                       //以m為起點(diǎn)向4個(gè)方向BFS
                        xx = tx + move[i][0];
                        yy 
= ty + move[i][1];
                        
if(!flag[xx][yy] && legal(xx,yy)){
                                flag[xx][yy] 
= true;
                                tep.x 
= xx;
                                tep.y 
= yy;
                                tep.num 
= num + 1;
                                f.push(tep);
                                
if(num+1>maxt){                                            //如果有更大的則更新
                                        maxt = num + 1;
                                        ans 
= tep;
                                }
                        }
                }
                f.pop();                                                                              
//彈出隊(duì)首元素
        } 
}
int main(){
        
int i,j,T;
        Node start,end;
        
bool mark;
        scanf(
"%d",&T);
        
while(T--){
                scanf(
"%d%d",&c,&r);
                mark 
= false; maxt = -1;
                
for(i = 0;i < r; i++)
                        scanf(
"%s",map[i]);
                
for(i = 0;i < r; i++){
                        
for(j = 0;j < c; j++){
                                
if(map[i][j]=='.'){                                                     //任選一點(diǎn)BFS
                                        start.x = i;
                                        start.y 
= j;
                                        start.num 
= 0;
                                        bfs(start);
                                        mark 
= true;
                                        
break;
                                }
                        }
                        
if(mark) break;
                }
                maxt 
= -1;ans.num = 0;                                                           //此時(shí)ans一定是直徑的端點(diǎn),將它設(shè)為起點(diǎn)
                bfs(ans);                                                                                    //進(jìn)行第二次BFS
                printf("Maximum rope length is %d.\n",maxt);
        }
}


TOJ3517(The longest athletic track):
          題目給出了一棵生成樹,問這棵生成樹最長(zhǎng)的路的長(zhǎng)度是多少。

#include<iostream>
#include
<queue>
#define INF 999999
#define M 2002
using namespace std;
int n;
int maxx;
int map[M][M],sum[M];
bool flag[M];
int bfs(int begin){
            queue
<int>f;
           
int i,m,k,key;
            maxx
=0;
            memset(flag,
false,sizeof(flag));
            f.push(begin);
           
while(!f.empty()){
                        k
=f.front();
                        
for(i=1;i<=n;i++){
                                
if(map[k][i]!=INF&&!flag[i]){
                                            flag[i]
=true;
                                            f.push(i);
                                            sum[i]
=sum[k]+map[k][i];
                                            
if(sum[i]>maxx) { maxx=sum[i];key=i; }
                                 }
                         }
                         f.pop();
            }
           
return key;
}
int main()
{
           
int i,j,k,dis,key,cas;
            scanf(
"%d",&cas);
           
while(cas--){
                         scanf(
"%d",&n);
                        
for(i=1;i<n;i++)
                                  
for(j=i+1;j<=n;j++)
                                            map[i][j]
=map[j][i]=INF;
                        
for(i=1;i<n;i++){
                                   scanf(
"%d%d%d",&j,&k,&dis);
                                   map[j][k]
=map[k][j]=dis;
                         }
                         sum[
1]=0;
                         key
=bfs(1);
                         sum[key]
=0;
                         key
=bfs(key);
                         printf(
"%d\n",maxx);
             }
    
//system("pause");
}





posted @ 2010-07-08 01:14 M.J 閱讀(2675) | 評(píng)論 (0)編輯 收藏

歸并排序求逆序?qū)?/a>

              早就想學(xué)一下歸并排序求逆序?qū)Γ谶@之前只會(huì)用樹狀數(shù)組來做,有時(shí)候還需要離散化,而且效率還不如歸并排序高。
              其實(shí)還是蠻簡(jiǎn)單的,知道歸并排序的原理就很容易知道如何求逆序?qū)α恕TO(shè)數(shù)組為A,關(guān)鍵是在合并的時(shí)候,用數(shù)組L 和 R 表示左右兩個(gè)子數(shù)組,因?yàn)槟嫘驅(qū)Φ膫€(gè)數(shù)f(A) = f(L) + f(R) + s(L,R);其中f(L) 和 f(R) 分別表示L 內(nèi)部 和R內(nèi)部的逆序?qū)€(gè)數(shù),s(L.R)表示大數(shù)在L,小數(shù)在R的逆序?qū)ΑR驗(yàn)長(zhǎng)和R是已經(jīng)排好序的,故其實(shí)只需求s(L,R).這個(gè)可以在合并L和R依次進(jìn)行比較的時(shí)候算出。
for(k = p;k <= r;k ++){
         
if(L[i]<=R[j])
                  a[k] 
= L[i++];
         
else{                                                //如果L最上面的數(shù)大于R的,那么L[i]及后面的數(shù)可以和R[j]構(gòu)成n1-i+1個(gè)逆序?qū)?br>                  a[k] = R[j++];
                  count 
+=(n1 -+ 1);              //累加
          }
}

歸并排序的代碼:

void merge(int p,int q,int r){
         
int n1 = q-p+1,n2 = r-q;
         
int i,j,k;
         
for(i = 1;i <= n1; i++)
                   L[i] 
= a[p+i-1];
         
for(j = 1;j <= n2; j++)
                   R[j] 
= a[q+j];
          L[n1
+1= INF;
          R[n2
+1= INF;
          i 
= 1;j = 1;
         
for(k = p;k <= r;k ++){
                  
if(L[i]<=R[j])
                             a[k] 
= L[i++];
                  
else{
                             a[k] 
= R[j++];
                             count 
+=(n1 -+ 1);
                   }
          }
}
void merge_sort(int p,int r){
         
if(p<r){
                  
int q = (p+r)/2;
                   merge_sort(p,q);
                   merge_sort(q
+1,r);
                   merge(p,q,r);
          }
}


posted @ 2010-07-08 00:07 M.J 閱讀(2728) | 評(píng)論 (1)編輯 收藏

多重背包問題

今天看了下多重背包,理解的還不夠深入,不過因?yàn)槭?1背包過來的,所以接受起來很容易。
主要是運(yùn)用了二進(jìn)制的思想將一個(gè)數(shù)量為N很大的物品分為了logN個(gè)數(shù)量小的物品,而這logN個(gè)物品可以組成數(shù)量為0到N任意數(shù)量,所以這種策略是
成立的。
多重背包問題有TOJ1034,TOJ1670.

TOJ1034 :
大意是有6種規(guī)格的石頭,編號(hào)從1到6,編號(hào)為 i 的石頭的價(jià)值為 i .現(xiàn)在給出各種石頭的數(shù)量,問有沒有可能得到總價(jià)值的一半。
做法:    DP, 每種石頭價(jià)值為v[i],價(jià)值為 i ,數(shù)量為 num[i] ,通過多重背包看能不能恰好取得總價(jià)值的一半。
           一個(gè)優(yōu)化是總價(jià)值為奇數(shù)直接不用考慮,而在DP的時(shí)候設(shè)置一個(gè)標(biāo)記來記錄是否已經(jīng)取得總價(jià)值一半,如果取得則可以返回。
做法2:這種方法的前提是POJ  discuss里的一種做法,即給每個(gè)石頭的數(shù)量mod 8。證明是用抽屜原理證的,很復(fù)雜,我沒有看。但是這樣以來,數(shù)量
            一下子大大減少,極大的提高了效率。
            我說的做法2事實(shí)上是我的最初做法,即DFS,搜索,在搜索過程中注意剪枝,再加上數(shù)量取模的優(yōu)化,復(fù)雜度也不高。 

Code for 1034(Dividing):
import java.util.Scanner;

import java.util.
*;

import javax.swing.plaf.basic.BasicInternalFrameTitlePane.MaximizeAction;
public class Main {
    
public static int f[] = new int[20001*6];                                                // f[i]表示容量為 i 的背包最多能裝的物品的價(jià)值
    
public static int v[] = new int[7];
    
public static int num[] = new int[7];
    
public static int total,flag,key;                                                               //total為 6 種大理石的總價(jià)值 ,flag為標(biāo)記,一旦為1表示可以取得,可以返回了
    
public static void onezeropack(int cost,int weight) {                           //  01背包函數(shù),注意循環(huán)是從total 到 cost,不要弄反
             
int i;
             
for(i = total;i >= cost; i--) {
                        f[i] 
= Math.max(f[i],f[i-cost]+weight);
                       
if(f[i] == key) {                                                                 // 如果可以取得總價(jià)值一半,flag=1,返回
                                  flag 
= 1;
                                 
return ;
                        }
              }
    }
    
public static void finishpack(int cost,int weight) {                            
             
int i;
             
if(flag==1return ;
             
for(i = cost;i <= total; i++) {
                         f[i] 
= Math.max(f[i], f[i-cost]+weight);
                       
if(f[i] == key) {
                                flag 
= 1;
                               
return ;
                        }
              }
    }
    
public static void multipack(int cost,int weight,int amount) {
                
if(cost*amount >= total) {
                            finishpack(cost, weight);
                           
return ;
                 }
                
if(flag==1return ;
                
int k = 1;
                
while(k < amount) {                                                                                        // 該過程即為將一件物品拆分為1,2,4...2^k 件物品進(jìn)行01背包過程
                            onezeropack(k
*cost, k*weight);
                            amount 
-= k;
                            k 
*= 2;
                 }
                 onezeropack(cost
*amount, weight*amount);
    }
    
public static void main(String[] args){
                 Scanner 
in = new Scanner(System.in);
                
int i,j,cas = 1;
                
while(true) {
                            Arrays.fill(f,
0);
                            total 
= 0; flag = 0;
                           
for(i = 1;i <= 6; i++) {
                                       num[i] 
= in.nextInt();
                                       v[i] 
= i;
                                       total 
+= i*num[i];
                            }
                          
if(num[1]==0&&num[2]==0&&num[3]==0&&num[4]==0&&num[5]==0&&num[6]==0)
                                     
break;
                          
if(total%2==1) flag = 0;
                          
else {
                                     key 
= total/2;
                                    
for(i = 1;i <= 6; i++
                                     multipack(i, i, num[i]);
                           }
                           System.
out.println("Collection #"+cas+":");
                          
if(flag==0) System.out.println("Can't be divided.");
                          
else System.out.println("Can be divided.");
                           System.
out.println();
                           cas
++;
                }
    }

}

TOJ 1670:
          大意是一臺(tái)取款機(jī)有N中貨幣,每種貨幣面值為 V[i] ,數(shù)量為 num[i] , 給出一個(gè)價(jià)值,為在這個(gè)價(jià)值之內(nèi)(包括這個(gè)價(jià)值)最大能取得多大。
分析:典型的多重背包,給出的價(jià)值即為背包容量,每種貨幣為一種物品,價(jià)值為v[i] , 數(shù)量為num[i],求能得到的最大價(jià)值。
          注釋就不加了,參考上面的程序

Code for 1670(Cash Mechine):

#include <cstdio>
#include 
<cstring>

int f[100002],v[12],num[12],cost[12];
int total,n;
int max(int a,int b){ return a>b?a:b;}

void OneZeroPack(int cost,int value){
          
int i,j;
          
for(i = total;i >= cost; i--)
                   f[i] 
= max(f[i],f[i-cost]+value);

}
void completePack(int cost,int weight){
          
int i;
          
for(i = cost;i <= total; i++)
                   f[i] 
= max(f[i],f[i-cost]+weight);
}
void multiPack(int cost,int weight,int amount){
          
if(cost*amount >= total){
                   completePack(cost,weight);
                  
return ;
           }
          
int k = 1;
          
while(k < amount){
                   OneZeroPack(k
*cost,k*weight);
                   amount 
-= k;
                   k
*=2;
           }
           OneZeroPack(cost
*amount,amount*weight);
}
int main(){
          
int i,j,k;
          
while(scanf("%d%d",&total,&n)!= EOF){
                   memset(f,
0,sizeof(f));
          
for(i = 1;i <= n; i++){
                   scanf(
"%d%d",&num[i],&cost[i]);
                   v[i] 
= cost[i];
           }
          
for(i = 1;i <= n; i++)
                   multiPack(cost[i],v[i],num[i]);
                   printf(
"%d\n",f[total]);    
           }
}



posted @ 2010-07-07 20:18 M.J 閱讀(799) | 評(píng)論 (0)編輯 收藏

TOJ 3446.Money Matters 并查集,路徑壓縮

        題目大意是N個(gè)人互相有債a[i](正的表示別人欠錢,否則表示自己欠別人錢,a[i]的和保證為0),但是這N個(gè)人只有朋友間才能互相算帳,現(xiàn)在給出N個(gè)人的債,并且給出M個(gè)關(guān)系,即誰和誰是朋友,最后問有沒有可能所有人都把帳算清。


Sample Input 1:                         Sample Input 2:

5    3                                            4     2
100                                              15
-75                                               20
-25                                              -10
-42                                              -15
42                                                0  2
0 1                                               1  3
1 2
3 4

Sample Output 1:                       Sample Output  2:

POSSIBLE                                    IMPOSSILBE

 思路1:

              每輸入一個(gè)關(guān)系,合并,最后從1到N,對(duì)于每一個(gè)人,找出它們的祖先,將他們的債debt加到祖先的debt

              上。通俗的講,就是每個(gè)集合的成員都將自己的debt加到祖先上,自己歸0,最后看祖先的值是否為0;

              最后在從1到N掃一遍如果有debt不為0的,輸出“IMPOSSIBLE”,否則“POSSIBLE”;

              缺點(diǎn):復(fù)雜度高,查詢復(fù)雜度*N,最后勉強(qiáng)過了,時(shí)間0.63s

思路2:

              路徑壓縮,每輸入一個(gè)關(guān)系,合并。最后從1到N,如果 i 的debt不為0,從 i 到 i 的祖先的路徑不斷壓縮直到

              祖先,這樣雖然仍然是N次操作,但由于在壓縮過程中大部分成員debt歸0,故實(shí)際上進(jìn)行操作的次數(shù)遠(yuǎn)小于N.

              最后時(shí)間為0.11,比起上一種方法有了很大提高

Code 1:

#include <cstdio>
#include 
<cstring>
struct Node{
        
int father,v,num;
}a[
10002];
int find(int n){
        
int tep,m = n;
        
while(n != a[n].father)
                n 
= a[n].father;
        
while(m != n){
                tep 
= a[n].father;
                a[n].father 
= n;
                m 
= tep;
        }
        
return n;
}
void Union(int root1,int root2){
        
int t1,t2;
        t1 
= find(root1),t2 = find(root2);
        
if(t1 == t2) return ;
        
else{
                
if(a[t1].v > a[t2].v){
                        a[t1].v 
+= a[t2].v;
                        a[t2].father 
= t1;
                }
                
else{
                        a[t2].v 
+= a[t1].v;
                        a[t1].father 
= t2;
                }
        }
}
int main()
{
        
int n,m,i,j;
        
bool flag = false;
        scanf(
"%d%d",&n,&m);
        
for(i = 0;i < n; ++i){
                a[i].father 
= i,a[i].v = 0;
                scanf(
"%d",&a[i].num);
        }
        
while(m--){
                scanf(
"%d%d",&i,&j);
                Union(i,j);
        }
        
for(i = 0;i < n; ++i){
                
int tep = find(i);
                
int tt = a[i].num;
                a[i].num 
-= tt;
                a[tep].num 
+= tt;
        }
        
for(i = 0;i < n; i++)
                
if(a[i].num != 0){
                        flag 
= true;
                        
break;
                }
        
if(flag) printf("IMPOSSIBLE\n");
        
else     printf("POSSIBLE\n");
}

Code 2:

#include <cstdio>
#include 
<cstring>
struct Node{
        
int father,v,num;
}a[
10002];
int find(int n){
        
int m = n,tep;
        
while(n != a[n].father)
                n 
= a[n].father;
        
while(m != n){
                tep 
= a[m].father;
                
int tt = a[m].num;
                a[m].num 
-= tt;
                a[tep].num 
+= tt;
                a[m].father 
= n;
                m 
= tep;
        }
        
return n;
}
void Union(int root1,int root2){
        
int t1,t2;
        t1 
= find(root1),t2 = find(root2);
        
if(t1 == t2) return ;
        
else{
                
if(a[t1].v > a[t2].v){
                        a[t1].v 
+= a[t2].v;
                        a[t2].father 
= t1;
                }
                
else{
                        a[t2].v 
+= a[t1].v;
                        a[t1].father 
= t2;
                }
        }
}
int main()
{
        
int n,m,i,j;
        
bool flag = false;
        scanf(
"%d%d",&n,&m);
        
for(i = 0;i < n; ++i){
                a[i].father 
= i,a[i].v = 0;
                scanf(
"%d",&a[i].num);
        }
        
while(m--){
                scanf(
"%d%d",&i,&j);
                Union(i,j);
        }
        
for(i = 0;i < n; ++i)
             
if(a[i].num != 0) find(i);
        
for(i = 0;i < n; i++)
                
if(a[i].num != 0){
                        flag 
= true;
                        
break;
                }
        
if(flag) printf("IMPOSSIBLE\n");
        
else     printf("POSSIBLE\n");
}








posted @ 2010-07-05 21:08 M.J 閱讀(325) | 評(píng)論 (0)編輯 收藏

TOJ 1688. Corporative Network 并查集

       這道題題意很難懂,大意是有N個(gè)公司,每個(gè)公司有一個(gè)center,最初每個(gè)公司的center都在自己公司,然后有M次操作,每次操作 A , B (A保證是一個(gè)集合的center,B不一定) 表示將A所在的集合并到B所在的集合,且B的center成為了A的center。每次操作后兩個(gè)公司的線的距離增加abs(A-B)%1000;
Sample Input: (E  P表示查詢P距離自己center的線的長(zhǎng)度,I   P  Q 表示合并 P ,Q);
1
4
E 3
I 3 1
E 3
I 1 2
E 3
I 2 4
E 3
O
Sample Output:
0
2
3
5

Code:
#include <cstdio>
#include 
<iostream>
#define M 20010
using namespace std;

struct Node{
        
int father,num;
}a[M];
void initial(int n){
        
int i;
        
for(i = 1;i <= n; i++){
                a[i].father 
= i;
                a[i].num 
= 0;
        }
}
int find(int n){
        
int tep,m = n;
        
if(n == a[n].father) return n;
        find(a[n].father);               
//遞歸查找n的祖先
        a[n].num += a[a[n].father].num;   //n的直需要更新(加上n的父親的值)
        a[n].father = a[a[n].father].father;
}
int main()
{
        
int T,n,i,j,k;
        
char order[3];
        scanf(
"%d",&T);
        
while(T--){
                scanf(
"%d",&n);
                initial(n);
                
while(scanf("%s",order)){
                        
if(order[0]== 'O'break;
                        
if(order[0== 'E'){
                                scanf(
"%d",&k);
                                find(k);
                                printf(
"%d\n",a[k].num);
                        }
                        
else{
                                scanf(
"%d%d",&j,&k);
                                
int dis = abs(j-k)%1000;
                                a[j].num 
= dis;           //該值dis為j的值
                                a[j].father = k;          //k成為了j的父親
                        }
                }
        }
}





posted @ 2010-07-05 20:48 M.J 閱讀(156) | 評(píng)論 (0)編輯 收藏

TOJ 2904【JAVA大數(shù)的進(jìn)制問題】

題目給定一個(gè)進(jìn)制b,然后給兩個(gè)b進(jìn)制下的大數(shù) m 和 n ,要求求出m % n的結(jié)果,用b進(jìn)制表示。
最近在學(xué)JAVA,發(fā)現(xiàn)做起高精度簡(jiǎn)直太爽了~ 這個(gè)題有JAVA簡(jiǎn)直就是個(gè)水題,知道一些函數(shù)就好了。
BigInteger a = in.nextBigInteger(base);       //將一個(gè)大數(shù)按照base進(jìn)制輸入
a.mod(b) ;                                                 //a%b,其中a和b都是大數(shù)且結(jié)果為10進(jìn)制,不管a和b是什么進(jìn)制
String str= a.toString(base);                      //將一個(gè)大數(shù)a轉(zhuǎn)換成b進(jìn)制的字符串

這個(gè)題就用到這些東西,代碼就不貼了。~~

posted @ 2010-06-23 16:05 M.J 閱讀(253) | 評(píng)論 (0)編輯 收藏

TOJ 1135 Matrix Chain Multiplication

很簡(jiǎn)單的題,給定N個(gè)矩陣,然后給出一系列運(yùn)算式,用括號(hào)來限制運(yùn)算,最后求一共進(jìn)行了多少次乘法運(yùn)算。
R(m,s) 和Q(s,n)相乘,要進(jìn)行m*s*n次~
處理運(yùn)算先后的時(shí)候,用棧實(shí)現(xiàn),即后進(jìn)先出就可以了。
Sample Input:
9
A 50 10
B 10 20
C 20 5
D 30 35
E 35 15
F 15 5
G 5 10
H 10 20
I 20 25
A
B
C
(AA)
(AB)
(AC)
(A(BC))
((AB)C)
(((((DE)F)G)H)I)
(D(E(F(G(HI)))))
((D(EF))((GH)I))
Sample Outout:
0
0
0
error
10000
error
3500
15000
40500
47500
15125
Code:
#include <iostream>
#include 
<cstdio>
#include 
<string>
#include 
<map>
using namespace std;

struct Matrx{
        
char id;
        
int x,y;
}a[
30];
Matrx stack[
100];
int main()
{
        
int i,j,k,n,ans;
        
bool flag;
        map
<char,int>mark;
        scanf(
"%d",&n);
        
for(i = 1;i <= n; i++){
                cin 
>> a[i].id;
                scanf(
"%d%d",&a[i].x,&a[i].y);
                mark[a[i].id] 
= i;
        }
        
string str;
        
while(cin>>str){
                ans 
= 0; flag = true;
                
int len = str.length();
                
int head,tail;
                head 
= tail = 0;
                
for(i = 0;i <len; i++){
                        
if(str[i] == '(')
                                
continue;
                        
else if(str[i] == ')'){     //pop
                                if(head == 1)
                                        head 
--;
                                
else if(head > 1){
                                        
int tx = stack[head-2].x;
                                        
int ty = stack[head-1].y;
                                        
if(stack[head-2].y != stack[head-1].x) flag = false;
                                        ans 
+= stack[head-2].x*stack[head-2].y*stack[head-1].y;
                                        head 
-= 2;
                                        stack[head].x 
= tx;
                                        stack[head
++].y = ty;
                                }

                        }
                        
else{        // push
                                stack[head++= a[mark[str[i]]];

                        }
                }
                
if(!flag) printf("error\n");
                
else printf("%d\n",ans);
        }
}




posted @ 2010-06-12 22:10 M.J 閱讀(190) | 評(píng)論 (0)編輯 收藏

【DP】TOJ 2820 How many different ways

給定從1 到 N的 N 個(gè)數(shù),問有多少種不同方案劃分這些數(shù)。比如N = 3,則有5種方案:
{{1},{2},{3}}
{{1,2},{3}}
{{1,3},{2}}
{{2,3},{1}}
{{1,2,3}}
最后的結(jié)果只保留后四位,即mod10000;
上網(wǎng)查了下,集合的劃分的個(gè)數(shù)叫做bell數(shù),bell數(shù)可以遞歸求解:
bell[0] = 1;
bell [n + 1] = sigma(C(n,k))*(bell[k]); (0<=k<=n)

 
然而這個(gè)題卻不可以這樣做,因?yàn)镹得范圍是2000,這樣做必定超時(shí),于是想到了DP,如果用dp[i][j]表示i個(gè)數(shù)
劃分成j個(gè)集合,那么便有dp[i][j] = j * dp[i-1][j] + dp[i-1][j-1];( i > j )直觀理解就是,將i個(gè)數(shù)劃分成j個(gè)集合的個(gè)數(shù),即為i-1個(gè)數(shù)劃分到j(luò)個(gè)集合的數(shù),再將多的那個(gè)依次放到j(luò)個(gè)集合中,所以乘以j,或者是i-1個(gè)數(shù)放在j-1個(gè)集合中,第j個(gè)集合為空,則正好將多的這個(gè)數(shù)放到這個(gè)集合中,于是便有上邊的狀態(tài)轉(zhuǎn)移方程。
Code:

 

#include <cstdio>
#include 
<iostream>
#include 
<cmath>
using namespace std;

int map[2002][2002];
void DP(){
    memset(map,
0,sizeof(map));
    
int i,j,k;
    
for(i = 0;i <= 2000; i++){
        map[i][i] 
= 1;
        map[i][
1= 1;
    }

    
for(i = 0;i <= 2000 ;i++)
        
for(j = 0; j < i; j++)
            map[i][j] 
= (j * map[i-1][j] + map[i-1][j-1])%10000;
}

int main()
{
    
int i,j,k,n;
    DP();
    
while(scanf("%d",&n),n){
        
int ans = 0;
        
for(i = 0;i <= n; i++)
            ans 
= (ans + map[n][i])%10000;
        
string str = "0000";
        str[
3= ans%10+'0'; ans/=10;
        str[
2= ans%10+'0'; ans/=10;
        str[
1= ans%10+'0'; ans/=10;
        str[
0= ans%10+'0'; ans/=10;
        cout
<<str<<endl;
    }

}

posted @ 2010-06-12 15:05 M.J 閱讀(330) | 評(píng)論 (0)編輯 收藏

Dilworth定理及相關(guān)題目

偏序集的兩個(gè)定理:
定理1) 令(X,≤)是一個(gè)有限偏序集,并令r是其最大鏈的大小。則X可以被劃分成r個(gè)但不能再少的反鏈。
其對(duì)偶定理稱為Dilworth定理:
定理2) 令(X,≤)是一個(gè)有限偏序集,并令m是反鏈的最大的大小。則X可以被劃分成m個(gè)但不能再少的鏈。
 即:鏈的最少劃分?jǐn)?shù)=反鏈的最長(zhǎng)長(zhǎng)度
相關(guān)的題目有pku 1065,pku 3636,pku 1548
POJ 3636:
#include<iostream>
#include
<algorithm>
#define M 20002
using namespace std;
struct Node{
    
int h,w;
}
a[M];
int tail[M],n;
void LIS(int n){
    
int i,j,m,len,mid,low,high;
    len
=1;tail[1]=a[1].h;
    
for(i=2;i<=n;i++){
        
if(tail[len]<=a[i].h) {
            len
++;
            tail[len]
=a[i].h;
        }

        
else{
            low
=1;high=len; 
            
while(low<high){
                mid
=(low+high)/2;
                
if(a[i].h>=tail[mid]) low=mid+1;
                
else high=mid;
            }

            tail[low]
=a[i].h;
        }

    }
                    
    printf(
"%d\n",len);      
}

bool cmp(Node a,Node b){
    
if(a.w!=b.w)return a.w>b.w;
    
else return a.h<b.h;
}

int main()
{
    
int i,j,k,cas;
    scanf(
"%d",&cas);    
    
while(cas--){
        scanf(
"%d",&n);
        
for(i=1;i<=n;i++)
            scanf(
"%d%d",&a[i].w,&a[i].h);
        sort(a
+1,a+1+n,cmp);
        LIS(n);
    }

    
//system("pause");
    return 0;
}
POJ  1548:
#include<iostream>
#include
<algorithm>
using namespace std;
int k,a[700],tail[800],b[860];
void LIS(){
    
int i,j,m,n,len,mid,left,right;
    n
=1;
    
for(i=k-1;i>=1;i--) b[n++]=a[i];
    n
--;
    len
=1;tail[1]=b[1];
    
for(i=2;i<=n;++i){
        
if(b[i]>tail[len]){
            len
++;
            tail[len]
=b[i];
        }

        
else{
            left
=1;right=len;
            
while(left<right){              //二分查找插入的位置 
                mid=(left+right)/2;
                
if(tail[mid]<b[i]) left=mid+1;
                    
else  right=mid;
                }

            tail[left]
=b[i];                //插入 
        }
 
    }
                    
    printf(
"%d\n",len);      
}

int main()
{
    
int i,j,m,n;
    
while(1){
        k
=1;
        scanf(
"%d%d",&i,&j);
        
if(i==-1&&j==-1break;
        a[k
++]=j;
        
while(scanf("%d%d",&i,&j)){
            
if(i==0&&j==0 ){
                LIS();
                
break;        
            }

            a[k
++]=j;
        }
    
    }

}

posted @ 2010-05-28 18:35 M.J 閱讀(1102) | 評(píng)論 (0)編輯 收藏

僅列出標(biāo)題
共4頁: 1 2 3 4 
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久综合伊人77777蜜臀| 国产一区二区精品久久99| 日韩亚洲欧美成人一区| 亚洲激情在线| 欧美好骚综合网| 亚洲国产精品久久久久婷婷884 | 午夜精品久久久久久久| 欧美一区日韩一区| 麻豆av福利av久久av| 亚洲国产精品999| 亚洲一区二区在线播放| 久久精品国产99精品国产亚洲性色| 久久久久久有精品国产| 欧美激情一区二区三区在线视频 | 亚洲深夜福利网站| 欧美一区免费| 免费成人av在线看| 国产精品jizz在线观看美国 | 亚洲尤物视频网| 久久在线播放| 欧美三区在线视频| 精品成人一区二区三区| 在线视频精品| 久久一区激情| 中文在线不卡| 免费在线成人| 国产亚洲综合精品| 中文在线一区| 欧美成人精品三级在线观看| 宅男在线国产精品| 免费观看成人鲁鲁鲁鲁鲁视频| 欧美一级免费视频| 伊人久久婷婷色综合98网| 亚洲伦理一区| 久久免费视频一区| 亚洲视频在线一区| 欧美国产亚洲另类动漫| 韩国三级电影久久久久久| 99视频有精品| 欧美大色视频| 欧美在线影院| 国产精品日韩一区| 亚洲视频第一页| 亚洲国产精品电影在线观看| 欧美在线日韩在线| 国产欧美一区二区精品忘忧草 | 免费久久精品视频| 国产精品爽爽ⅴa在线观看| 99精品欧美一区二区蜜桃免费| 久久中文在线| 午夜欧美大片免费观看| 欧美日韩在线播放| 99xxxx成人网| 亚洲日本aⅴ片在线观看香蕉| 麻豆精品精华液| 亚洲高清不卡| 欧美激情精品久久久久| 久久亚洲影音av资源网| 一区在线观看视频| 另类图片综合电影| 看片网站欧美日韩| 亚洲国产精品一区二区久 | 亚洲综合精品自拍| 国产精品久久久久久av下载红粉| 99精品欧美一区二区蜜桃免费| 亚洲国产精品传媒在线观看| 欧美大片免费看| 日韩图片一区| 亚洲乱码一区二区| 国产精品magnet| 欧美综合国产| 久久久成人精品| 在线观看国产精品网站| 欧美大胆成人| 欧美猛交免费看| 亚洲男人第一网站| 欧美一区二区私人影院日本 | 欧美在线地址| 欧美中文在线字幕| 亚洲国产精品成人一区二区| 亚洲激情在线视频| 欧美人与禽猛交乱配视频| 亚洲欧美日韩天堂| 欧美一区二区视频免费观看| 欧美国产日韩亚洲一区| 欧美日韩成人一区二区| 夜夜爽www精品| 亚洲在线观看视频| 黄网站免费久久| 亚洲人成网站精品片在线观看| 欧美午夜精品久久久久免费视 | 亚洲片区在线| 欧美视频精品在线| 久久久久久穴| 欧美精品一区二区三区蜜桃| 欧美亚洲一区三区| 久久综合网络一区二区| 亚洲自拍偷拍麻豆| 久久亚洲欧洲| 欧美一区二区三区喷汁尤物| 久久人体大胆视频| 亚洲欧美激情一区二区| 老司机午夜精品| 午夜精品免费| 欧美成人一区二区三区在线观看| 香蕉国产精品偷在线观看不卡| 老司机精品视频一区二区三区| 亚洲与欧洲av电影| 免费成人黄色| 欧美96在线丨欧| 国产欧美日韩在线 | 日韩视频精品在线| 伊人久久婷婷| 午夜精品久久久久久久久久久久 | 欧美另类女人| 欧美99久久| 国语精品中文字幕| 在线亚洲观看| 亚洲图片在线| 欧美激情第1页| 免播放器亚洲一区| 国产日韩欧美一区在线| av不卡在线| 一区二区三区精品视频| 欧美成人免费在线观看| 欧美va天堂| 亚洲高清激情| 久久久久久久激情视频| 久久久久一本一区二区青青蜜月| 国产精品美女久久久浪潮软件| 亚洲精品久久视频| 日韩视频不卡中文| 欧美日韩国产一中文字不卡| 亚洲人成网站色ww在线| 日韩午夜电影av| 欧美va天堂在线| 亚洲黄网站黄| 一本大道久久精品懂色aⅴ| 欧美激情a∨在线视频播放| 亚洲国产欧美在线| 一区二区三区国产精品| 欧美视频精品在线| 亚洲免费影视| 久久综合伊人77777蜜臀| 欧美成人在线网站| 韩日成人在线| 久久综合国产精品| 欧美激情按摩在线| 亚洲美女视频在线观看| 欧美日韩国产美| 中文亚洲视频在线| 欧美亚洲自偷自偷| 激情久久久久| 欧美激情视频给我| 中国成人亚色综合网站| 香港久久久电影| 在线播放视频一区| 欧美人与禽性xxxxx杂性| 一本色道久久综合狠狠躁的推荐| 亚洲一区免费| 激情另类综合| 欧美理论在线| 性久久久久久久久久久久| 久久亚洲欧美国产精品乐播| 91久久线看在观草草青青| 欧美日韩一级黄| 先锋影院在线亚洲| 亚洲丁香婷深爱综合| 亚洲一区二区久久| 激情久久综艺| 国产精品不卡在线| 久久在精品线影院精品国产| 99pao成人国产永久免费视频| 欧美在线二区| aa成人免费视频| 国产亚洲一区在线播放| 欧美猛交免费看| 久久久亚洲高清| 亚洲午夜日本在线观看| 亚洲第一区色| 久久国产主播精品| 亚洲神马久久| 亚洲激情视频在线| 国产视频一区二区三区在线观看| 欧美jjzz| 久久九九热re6这里有精品| 99精品视频一区二区三区| 老司机67194精品线观看| 国产精品99久久久久久宅男| 亚洲第一在线综合在线| 国产欧美日韩在线观看| 欧美日韩专区| 欧美片第一页| 模特精品在线| 久久久亚洲精品一区二区三区| 一区二区三区精密机械公司| 亚洲电影免费观看高清完整版在线 | 1769国内精品视频在线播放| 久久电影一区| 亚洲免费在线电影|