随笔-141  评论-9  文章-3  trackbacks-0
 
     摘要: 据说,Hash的优劣顺序为:BKDRHash, APHash, DJBHash, JSHash, RSHash, SDBMHash, PJWHash, ELFHash。 unsigned int SDBMHash(char *str){    unsigned int hash = 0;...  阅读全文
posted @ 2011-02-23 22:16 小阮 阅读(379) | 评论 (0)编辑 收藏

题意:求最大子矩阵。

设h[i,j]是点(i, j)向上的最长距离,l[i,j]是点(i, j)向左的最长距离,r[i,j]是点(i, j) 向右的最常距离,

点(i, j)处的矩形面积 = h[i, j]*(l[i, j]+r[i, j]-1)

h[i, j] = h[i-1,j]+1  ( 点(i, j)是好的)
h[i, j] = 0              ( 点(i, j)是坏的)

l[i, j] = min( l[i-1, j] , k) ( 点(i, j)是好的)
l[i, j] = 0                       ( 点(i, j)是坏的)

r[i, j] = min(l[i-1, j], k) ( 点(i, j)是好的)
r[i, j] = 0                     ( 点(i, j)是坏的)


/*
ID: lorelei3
TASK: rectbarn
LANG: C++
*/


#include 
<fstream>

using namespace std;

const int MAX = 3005;

ifstream fin(
"rectbarn.in");
ofstream fout(
"rectbarn.out");

bool map[MAX][MAX];
int h[MAX], l[MAX], r[MAX];
int R,C,P,ans;

void input(){
    
int x,y;
    fin
>>R>>C>>P;
    
for(int i=0; i<P; ++i){
        fin
>>x>>y;
        map[x][y]
=true;
    }

}


inline 
int min(int a, int b){
    
if (a<&& a!=0
        
return a;
    
return b;
}


inline 
int max(int a, int b){
    
return a>b?a:b;
}

void dp(){
    
int i,j,k;
    
for(i=1; i<=R; ++i){
        k
=0;
        
for(j=1; j<=C; ++j){
            
if(!map[i][j]){
                h[j]
=h[j]+1;
                l[j]
=min(l[j], ++k);
            }
else
                h[j]
=0, l[j]=0, k=0;
        }


        k
=0;
        
for(j=C; j>=1--j){
            
if(!map[i][j]){
                r[j]
=min(r[j], ++k);
                ans
=max(ans, h[j]*(l[j]+r[j]-1));
            }
else
                r[j]
=0, k=0;
        }

    }

}


void output(){
    fout
<<ans<<endl;
}


int main(){
    
    input();

    dp();

    output();

    
return 0;
}
posted @ 2011-02-18 15:43 小阮 阅读(579) | 评论 (0)编辑 收藏
     摘要: 题意是求哈密顿回路的多少,可以用《基于连通性状态压缩的动态规划问题》来解,但由于只有4行,所以可以发现一些规律,其他人写的比较多了,就不列举出来,设f[i] 表示前i列中,第i列的第一个格子到第二个格子的哈密顿路的条数。本题的答案自然就是f[n]。设g[i]表示前i列中,第i列的第一个格子到第四个格子的哈密顿路的条数。f[i]的递推关系: f[i] = f[i-1] + g[i-1]g[i]的递推...  阅读全文
posted @ 2011-02-18 11:58 小阮 阅读(808) | 评论 (0)编辑 收藏
等待补充
posted @ 2011-02-18 11:50 小阮 阅读(440) | 评论 (0)编辑 收藏
     摘要: 后缀数组的简单应用。 /**//*ID: lorelei3TASK: hiddenLANG: C++*/#include <fstream>#include <iostream>#include <memory.h>using namespace std;const in...  阅读全文
posted @ 2011-02-17 17:10 小阮 阅读(491) | 评论 (0)编辑 收藏
将每个矩形拆分为2条横边和2条纵边,用一个结构体记录,

以横边为例,记录开始的横坐标s,结束的横坐标e,该横边的纵坐标p,若该横边是一个矩形下边的边,则start为ture,若是一个矩形上边的边,则为false,

记录后按纵坐标从小到大排序,若纵坐标相等的,start为ture的优先。

(PS:STL的sort中,对于比较函数,若两个元素相等,则必需返回false,否则会导致sort死循环)

排序后,从小到大进行扫描。

使用level作为记录数组,

对于start = true 的横边,对于j = [s, e) ,进行level[j] ++ 若level[j]==1, ans++;
对于start = false的横边,对于j = [s, e),进行level[j] --   若level[j]==0, ans++;

(画个简图领会下)

纵边如此类推。

/*
ID: lorelei3
TASK: picture
LANG: C++
*/


#include 
<fstream>
#include 
<algorithm>
#include 
<memory.h>

using namespace std;

const int MAX = 20005;

struct Line{
    
int s,e,p;
    
bool start;

    
bool operator < ( const Line &l) const{

        
if(p==l.p){
            
if(l.start == start)
                
return false;

            
if(start)
                
return 1;
            
else 
                
return 0;
        }

        
return p<l.p?1:0;
    }

}
;


ifstream fin(
"picture.in");
ofstream fout(
"picture.out");

Line lx[MAX], ly[MAX];
long ans;

int n,m;
void input(){
    fin
>>n;
    
int x1,x2,y1,y2,lenx=0,leny=0;
    m
=n+n;
    
for(int i=0; i<=n; ++i){
        fin
>>x1>>y1>>x2>>y2;
        lx[lenx].s
=x1, lx[lenx].e=x2, lx[lenx].p=y1;
        lx[lenx].start
=true;
        lenx
++;

        lx[lenx].s
=x1, lx[lenx].e=x2, lx[lenx].p=y2;
        lx[lenx].start
=false;
        lenx
++;

        ly[leny].s
=y1, ly[leny].e=y2, ly[leny].p=x1;
        ly[leny].start
=true;
        leny
++;

        ly[leny].s
=y1, ly[leny].e=y2, ly[leny].p=x2;
        ly[leny].start
=false;
        leny
++;
    }

    qsort(lx, m, 
sizeof(Line), cmp);
    qsort(ly, m, 
sizeof(Line), cmp);
    sort(lx, lx
+m);
    sort(ly, ly
+m);
}


int level[20005], zero=10000;
void solve(Line *l){

    memset(level, 
0sizeof(level));

    
for(int i=0; i<m; ++i){
        
if(l[i].start){
            
for(int k=zero+l[i].s; k<(zero+l[i].e); ++k){
                level[k]
++;
                
if(level[k]==1)
                    ans
++;
            }

        }
else{
            
for(int k=zero+l[i].s; k<(zero+l[i].e); ++k){
                level[k]
--;
                
if(level[k]==0)
                    ans
++;
            }

        }

    }

}


void output(){
    fout
<<ans<<endl;
}


int main(){
    input();
    solve(lx);
    solve(ly);
    output();
    
return 0;
}

posted @ 2011-02-17 13:56 小阮 阅读(405) | 评论 (0)编辑 收藏
     摘要: 本题是求最大点割集。首先,构造图。对于点i,分成u和v两点,并且dist[u][v]=1,dist[v][u]=0;对于边(i, j), 对于i,根据上述方法分成a1,a2两点,j分成b1,b2; 使dist[b1][a2]=INF,dist[a2][b1]=0; dist[b2][a1]=INF,dist[a1][b2]=0;然后根据最大流最小割定理,求最大流,使用Dinic。Dinic的原理是...  阅读全文
posted @ 2011-02-17 13:47 小阮 阅读(691) | 评论 (0)编辑 收藏

优化1:黑书P184, 一条完整的路径对于中间各点(除起点和目标点外),必需包含一进一出,所以中间点必需至少有两个未经过的相邻点(除非当前点在旁边)

优化2:预防形成孤零区域。

/*
ID: lorelei3
TASK: betsy
LANG: C++
*/


#include 
<fstream>

using namespace std;

const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
const int MAXN = 10;

ifstream fin(
"betsy.in");
ofstream fout(
"betsy.out");

bool map[MAXN][MAXN];

int n,ans,num;
void input(){
    fin
>>n;
    
for(int i=0; i<=n+1++i){
        map[
0][i]=true, map[i][0]=true, map[n+1][i]=true, map[i][n+1]=true;
    }

    num
=n*n;
}


inline 
int get(int x, int y){
    
int cnt=0;
    
for(int i=0; i<4++i)
        
if(!map[x+dx[i]][y+dy[i]])
            cnt
++;
    
return cnt;
}


void dfs(int x, int y, int t){
    
if(x==n&&y==1){
        
if(t==num)
            ans
++;
        
return;
    }


    
//优化2
    if(map[x][y-1]&&map[x][y+1]&&!map[x+1][y]&&!map[x-1][y] ||
        
!map[x][y-1]&&!map[x][y+1]&&map[x+1][y]&&map[x-1][y] )
        
return;

    
//优化1
    int i,xi,yi,count=0;
    
for(i=0; i<4++i){
        
int tx=x+dx[i];
        
int ty=y+dy[i];
        
if(map[tx][ty] || (tx==n&&ty==1))
            
continue;
        
int p = get(tx,ty);
        
if(p<=1){
            count
++;
            xi
=tx, yi=ty;
        }

    }


    
if(count>1)
        
return;
    
else{
        
if(count==1){
            map[xi][yi]
=true;
            dfs(xi,yi,t
+1);
            map[xi][yi]
=false;
        }
else{
            
for(i=0; i<4++i){
                
int tx=x+dx[i];
                
int ty=y+dy[i];
                
if(!map[tx][ty]){
                    map[tx][ty]
=true;
                    dfs(tx,ty,t
+1);
                    map[tx][ty]
=false;
                }

            }

        }

    }

}


void solve(){
    map[
1][1]=true;
    dfs(
1,1,1);
}




void output(){
    fout
<<ans<<endl;
}


int main(){

    input();

    solve();

    output();

    
return 0;
}


posted @ 2011-02-16 15:28 小阮 阅读(555) | 评论 (0)编辑 收藏

动态规划

posted @ 2011-02-16 15:23 小阮 阅读(409) | 评论 (0)编辑 收藏

可以看成甲乙两个人同时从A点出发,经过不同的路径,到达B点的最长路径和。

设f[i,j]为甲走到第i座城市,乙走到第j座城市,路径的总和。

初始状态:f[1][1]=1;

转移方程:f[j, i ] = f[i,j] = max{f[i,k]+1} j,k间有路,1<=k<j

结果:ans = max{f[i,n]} i,n之有路

/*
ID: lorelei
TASK: tour
LANG: C++
*/


#include 
<fstream>
#include 
<string>

using namespace std;

const int MAX = 105;
const int INF = 0x7FFFFFF;

ifstream fin(
"tour.in");
ofstream fout(
"tour.out");

string city[105];
bool adj[MAX][MAX];
int n,v,ans;

inline 
int find(string str){
    
for(int i=1; i<=n; ++i)
        
if(str==city[i])
            
return i;
}


void input(){
    
int i;
    fin
>>n>>v;
    
for(i=1; i<=n; ++i)
        fin
>>city[i];

    
string s,t;
    
for(i=1; i<=v; ++i){
        fin
>>s>>t;
        
int v1 = find(s);
        
int v2 = find(t);
        adj[v1][v2]
=adj[v2][v1]=true;
    }

}


int f[MAX][MAX];
void solve(){
    f[
1][1]=1;
    
for(int i=1; i<=n; ++i)
        
for(int j=i+1; j<=n; ++j){
            f[i][j]
=-INF;
            
for(int k=1; k<j; ++k){
                
if(adj[k][j] && f[i][k]>0 && f[i][k]>f[i][j])
                    f[i][j]
=f[i][k];
            }

            f[j][i]
= ++f[i][j];
        }

}


void output(){
    ans
=1;
    
for(int i=1; i<n; ++i)
        
if(adj[i][n] && f[i][n]>ans)
            ans
=f[i][n];
    fout
<<ans<<endl;
}


int main(){

    input();

    solve();

    output();

    
return 0;
}



 

posted @ 2011-02-14 22:49 小阮 阅读(544) | 评论 (1)编辑 收藏
仅列出标题
共14页: 1 2 3 4 5 6 7 8 9 Last