随笔-141  评论-9  文章-3  trackbacks-0
 

1. 用贪心分别算出A单独加工n个工件的时间f1, 和B单独加工n个工件的时间f2

2. 用f1 的最小值 + f2 最大值 , 用平均贪心的思想. 再比较最大值为第二问的解.

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


#include 
<fstream>
#include 
<algorithm>
#include 
<functional>

using namespace std;

const int MAXN = 1005;
const int MAXM = 35;

int t1[MAXM], t2[MAXM], w1[MAXM], w2[MAXM], f1[MAXN], f2[MAXN];

int main(){
    
int i,j, n, m1, m2;

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

    fin
>>n>>m1>>m2;

    
for(i=1; i<=m1; ++i)
        fin
>>t1[i];

    
for(i=1; i<=m2; ++i)
        fin
>>t2[i];

    
for(i=1; i<=n; ++i){
        
int min=1
        
for(j=2; j<=m1; ++j)
            
if(w1[j]+t1[j] < w1[min]+t1[min])
                min
=j;
        w1[min] 
+= t1[min];
        f1[i] 
= w1[min];

        min
=1;
        
for(j=2; j<=m2; ++j)
            
if(w2[j]+t2[j] < w2[min]+t2[min])
                min 
=j;
        w2[min] 
+= t2[min];
        f2[i] 
= w2[min];
    }


    sort(f1
+1, f1+n+1, less<int>());
    sort(f2
+1, f2+n+1, greater<int>());

    
int ans1 = f1[n], ans2 = 0;

    
for(i=1; i<=n; ++i)
        
if(f1[i]+f2[i] > ans2)
            ans2 
= f1[i]+f2[i];

    fout
<<ans1<<" "<<ans2<<endl;



    
return 0;
}
posted @ 2011-01-25 17:10 小阮 阅读(816) | 评论 (2)编辑 收藏

 

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


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

using namespace std;

const int MAXN = 205;

int a[MAXN][MAXN], match[MAXN];
int n,m, ans;
bool visited[MAXN];

bool dfs(int k){
    
for(int i=1; i<=a[k][0]; ++i){
        
int v = a[k][i];
        
if(!visited[v]){
            visited[v]
=true;
            
if(!match[v] || dfs(match[v])){
                match[v] 
= k;
                
return true;
            }

        }

    }

    
return false;
}


void search(){
    
for(int i=1; i<=n; ++i){
        memset(visited, 
0sizeof(visited));
        
if(dfs(i))
            ans
++;
    }

}


int main(){

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

    fin
>>n>>m;

    
for(int i=1; i<=n; ++i){
        fin
>>a[i][0];
        
for(int j=1; j<=a[i][0]; ++j){
            fin
>>a[i][j];
        }

    }


    search();

    fout
<<ans<<endl;

    
return 0;
}
posted @ 2011-01-25 10:48 小阮 阅读(401) | 评论 (0)编辑 收藏
标准的最大流. 注意有重边. 重复边直接累加.

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


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

using namespace std;

const int INF = 0x7FFFFFF;
const int MAXN = 205;

int s,t,n;

long long c[MAXN][MAXN], pre[MAXN], delta[MAXN];

bool bfs(int s, int t){
    
int i;
    queue
<int> Q;
    memset(pre, 
0sizeof(pre));
    memset(delta, 
0sizeof(delta));

    delta[s] 
= INF;
    Q.push(s);

    
while(!Q.empty()){
        
int cur = Q.front();
        Q.pop();

        
for(i=1; i<=n; ++i){
            
if(delta[i]==0 && c[cur][i]>0){
                delta[i] 
= delta[cur]<c[cur][i] ? delta[cur] : c[cur][i];
                pre[i] 
= cur;
                Q.push(i);
            }

        }

    }


    
if(delta[t]==0)
        
return false;

    
return true;
}


int edmonds_karp(int s, int t){
    
int i, ans=0;
    
while(bfs(s,t)){
        
for(i=t; i!=s; i=pre[i]){
            c[pre[i]][i] 
-= delta[t];
            c[i][pre[i]] 
+= delta[t];
        }

        ans 
+= delta[t];
    }

    
return ans;
}


int main(){

    
int k,i,j,v;

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

    fin
>>k>>n;

    s
=1; t=n;

    
while(k--){
        fin
>>i>>j>>v;
        c[i][j]
+=v;
    }


    fout
<<edmonds_karp(s,t)<<endl;

    
return 0;
}
posted @ 2011-01-24 22:42 小阮 阅读(210) | 评论 (0)编辑 收藏
     摘要: 剪枝:1. 对于任意串, 任意相邻的'C', 'O', 'W'之间的串应该在目标串中能找到.2. 通过ELFHash对串进行判重.( HASHSIZE可以大点)3. 若串的长度length 减去 目标串长度(47) MOD 3不等于0, 排除. /**//*ID: lorelei3TASK: cryptcowLANG: C++*/#include <...  阅读全文
posted @ 2011-01-24 00:25 小阮 阅读(673) | 评论 (0)编辑 收藏
     摘要: 求一个无向图的最小环,  建立模型比较简单, 输入数据的格式比较难受, 我采用了DFS, /**//*ID: lorelei3TASK: fence6LANG: C++*/#include <fstream>#include <memory.h>using namespace std;con...  阅读全文
posted @ 2011-01-23 09:48 小阮 阅读(449) | 评论 (0)编辑 收藏
多维背包问题, 不能DP, 由于搜索树又宽又深, 所以可以采取DFSID.

1. 对board、rail排序。并计算sum_board。对于每个rail,小的肯定比大的容易得到,取前k个rail的和 sum_rail,
     使得 sum_rail < sum_board && sum_rail + rail[k] > sum_board  

2. 从大到小枚举rail时,设from数组,保存每个rail是从哪个board来的,由于rail 肯定有重复,当rail[k] == rail[k+1]时候, 第k个rail的from值肯定是大于等于第k+1个rail来自的from,最少是from[k] = from[k+1];

3.设一个浪费值waste, n个rail之和sum_rail* (区别sum_rail), 则最多只能浪费 sum_board - sum_rail* 这么多木材,因为如果浪费更多的话,则剩余board肯定不够切

参考了USACO上边好多代码。。。

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


#include 
<fstream>
#include 
<iostream>
#include 
<algorithm>

using namespace std;

const int N = 55;
const int R = 1024;

bool flag;
int board[N], remain[N], from[N], rail[R];
int sum_board, sum_rail, max_waste, n, r,ans;
ifstream fin;
ofstream fout;

void dfs(int k, int waste){
    
if(k<0){
        flag 
=true;
        fout
<<ans+1<<endl;
        exit(
0);
    }
else{
        
int i;
        
if(k!= ans && rail[k] == rail[k+1]) 
            i 
= from[k+1];
        
else 
            i
=0;

        
for( ; i<n; ++i)
            
if(remain[i]>=rail[k]){
                from[k] 
= i;
                remain[i] 
-= rail[k];
                
if(remain[i] < rail[0])    waste += remain[i];
                
if(waste > max_waste){
                    waste 
-= remain[i];
                    remain[i] 
+= rail[k];
                    
continue;
                }

                dfs(k
-1, waste);
                remain[i] 
+= rail[k];
            }

    }
    
}


int main(){
    flag 
=false;
    
int i, nrail;

    fin.open(
"fence8.in");
    fout.open(
"fence8.out");

    fin
>>n;

    
for(i=0; i<n; ++i){
        fin
>>board[i];
        remain[i] 
= board[i];
        sum_board 
+= board[i];
    }


    fin
>>r;

    
for(i=0; i<r; ++i)
        fin
>>rail[i];

    sort(board, board
+n);
    sort(rail, rail
+r);

    
for(i=0; i<r; ++i){
        
if(sum_rail+rail[i]>sum_board) 
            
break;
        sum_rail
+=rail[i];
    }


    nrail 
= i;
    
    
for(i= nrail-1; i>=0--i){
        ans 
= i;
        max_waste 
= sum_board - sum_rail;
        sum_rail 
-= rail[i];
        dfs(i, 
0);
    }


    
if(!flag)
        fout
<<0<<endl;

    
return 0;
}



posted @ 2011-01-22 01:22 小阮 阅读(723) | 评论 (0)编辑 收藏

可以证明结果不会超过最大的两个数的最小公倍数(如果有的话, 这部分还没做)。

判断无限解可以按上面的方法,另外也可以算所有的数的最大公约数。

如果不是1,也就是说这些数不互质,那么一定没办法构成所有的不被这个最大公约数整除的数。当且仅当这种情况会有无限解。

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


#include 
<fstream>

using namespace std;

const int MAX = 70000;

bool f[MAX];
int n;
int a[15];

int gcd(int a, int b){
    
if(b==0)
        
return a;
    
else 
        
return gcd(b, a%b);
}


int main(){
    
int i,j,k;

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

    fin
>>n;

    
for(i=1; i<=n; ++i)
        fin
>>a[i];

    k
=a[1];
    
for(i=2; i<=n; ++i)
        k 
= gcd(k, a[i]);

    
if(k!=1){
        fout
<<0<<endl;
        
return 0;
    }


    f[
0]=true;

    
for(i=1; i<=n; ++i)
        
for(j=a[i]; j<=65536++j)
                f[j] = f[j]||f[j-a[i]];


    
for(i=65536; i>=1--i)
        
if(!f[i])
            
break;
    
    fout
<<i<<endl;
    
    
return 0;
}

posted @ 2011-01-20 20:34 小阮 阅读(263) | 评论 (0)编辑 收藏
f[i][j][k] 从前i首歌中选, 放入前j张碟, 每张蝶时间为k 的歌曲数量.

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


#include 
<fstream>

using namespace std;

const int MAX = 25;

int f[MAX][MAX][MAX];
int cost[MAX];

int N,T,M;

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


int main(){
    
int i,j,k;

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

    fin
>>N>>T>>M;

    
for(i=1; i<=N; ++i)
        fin
>>cost[i];

    
for(i=1; i<=N; ++i)
        
for(j=1; j<=M; ++j)
            
for(k=1; k<=T; ++k)
                
if(k<cost[i])
                    f[i][j][k] 
= max(f[i-1][j][k], f[i-1][j-1][T]); // 如果不选, 就取要这k分钟+以前的专辑的最优值 或 以前的专辑的最优值  
                else
                    f[i][j][k] 
= max(f[i-1][j][k-cost[i]], f[i-1][j-1][T])+1//取这首歌 取以前专辑的最优值+1 或 取当前专辑的最优值+1

    fout
<<f[N][M][T]<<endl;
            

    
return 0;
}
posted @ 2011-01-20 17:22 小阮 阅读(425) | 评论 (0)编辑 收藏

皮克定理说明了其面积S和内部格点数目a、边上格点数目b的关系:S = a + b/2 - 1。

根据三角形面积公式求出S。

如果知道了b,那么三角形内部格点数目a也就求出来了。

可以证明,一条直线((0,0),(n,m))上的格点数等于n与m的最大公约数+1。即b=gcd(n,m)+1. gcd(n,m)为n与m的最大公约数。

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


#include 
<fstream>
#include 
<cmath>
#include 
<iostream>

using namespace std;

int m,n,p;

int gcd(int a, int b){
    
if(b==0return a;
    
else return gcd(b, a%b);
}


int main(){
    
int S, a, b=0;
    ifstream fin(
"fence9.in");
    ofstream fout(
"fence9.out");

    fin
>>n>>m>>p;
    b 
+= gcd(n,m);
    b 
+= gcd(abs(n-p),m);
    b 
+= p;

    S 
= (p*m)/2;
    
//S = a + b/2 - 1;
    a = S+1-b/2;
    fout
<<a<<endl;
    
return 0;
}

代入皮克公式,即可求出a的值

posted @ 2011-01-19 19:04 小阮 阅读(244) | 评论 (0)编辑 收藏
采取递归的方法建立二叉树。
首先取前序遍历的首元素当作二叉树的根,当前元素为根。
把前序遍历中的当前元素当作中序遍历的分割点,中序遍历分割点前面的元素一定在当前元素的左子树,分割点后面元素一定在当前元素的右子树。然后加入下一个顶点,再把它当作分割点。
如此递归的进行,直到二叉树建立完成。
/*
ID: lorelei3
TASK: heritage
LANG: C++
*/


#include 
<fstream>
#include 
<iostream>
#include 
<memory.h>
#include 
<string.h>

using namespace std;

const int MAX = 100;
const int N = 10000;
int t;

char pre[MAX], mid[MAX], tree[N];

ifstream fin;
ofstream fout;

void Build(int n, char* pre, char* mid, int i){
    
if(n<=0)    
        
return;
    tree[i] 
= pre[0];
    
int p = strchr(mid, pre[0]) - mid;
    Build(p, pre
+1, mid, 2*i);
    Build(n
-p-1, pre+p+1, mid+p+12*i+1);
}


void PostOrder(int i){
    
if(tree[i]==NULL)
        
return;
    PostOrder(
2*i);
    PostOrder(
2*i+1);
    fout
<<tree[i];
}


int main(){
    fin.open(
"heritage.in");
    fout.open(
"heritage.out");

    memset(tree, NULL, 
sizeof(tree));

    fin
>>mid>>pre;

    Build(strlen(pre), pre, mid, 
1);

    PostOrder(
1);

    fout
<<endl;

    
return 0;
}
posted @ 2011-01-19 16:39 小阮 阅读(203) | 评论 (0)编辑 收藏
仅列出标题
共14页: First 3 4 5 6 7 8 9 10 11 Last