2011-03-16
USACO 4.4.2 Pollutant Control

中文题目
这题最小割的模型是比较好明白的,但是对于剩下的两个输出就比较难搞了,也就是割边最少和序号最小.后来问了下一个同学,他说对每一条边(E+1)再+1.这样就能得到割边最少的最小割集了,一想还真是,因为割边的最小集加的最少嘛.但是我想了下可以直接+1么?我的理解是1001之后更好算一些,*1001再+1的话maxflow就直接用修改后的maxflow/1001就行了,然后割边集就等于修改后的maxflow%1001.剩下的就是怎么按顺序输出了.这里可以按输入顺序一次一次枚举,去掉当前边,然后最大流,如果当前边+当前最大流==原来最大流的话,就输出当前边,当然可以修改总的最大流或者用一个变量记录已经输出量多少条边:
我的代码如下:

/
ID:qcx97811
LANG:C
TASK:milk6
/
#include
#include
#include
#include
long long n,m,maxflow
long long graph[36][36];
long long se[1006][3];//se[i][0]边的起点 se[i][1]边的终点se[i][2]表示权值
long long d[36],gap[36];

void sap()
{//sap求最大流
long long u,v
long long q[36],low[36];
long long tmp,front,rear
maxflow=0
//bfs
q[rear=0]=n;//这里是汇点
front=-1
memset(d,-1,sizeof(d));
memset(gap,0,sizeof(gap));
d[n]=0
while(front < rear)
{
u=q[++front];
for(v=1v<=n;v++)
{
if((-1==d[v])&(graph[v][u]>0))
{//这里是graph[v][u]不是graph[u][v]!!!
q[++rear]=v
d[v] = d[u]+1
gap[d[v]]++
}
}
}
//sap
q[tmp=0]=1
low[0]=INT_MAX//这里记得赋值
while(d[1]<n)
{
u=q[tmp];
for(v=1v<=n;v++)
{
if(graph[u][v]>0 & d[v]+1==d[u])
break
}
if((n+1)==v)
{//此点出度为0
gap[d[u]]
if(gap[d[u]] == 0)
break
d[u]=n+1
for(v=1v<=n;v++)
{
if(graph[u][v] > 0 & d[v] >=0 && d[v]+1<d[u])
d[u]=d[v]+1
}
gap[d[u]]++
if(tmp>0)
tmp
}
else
{
q[++tmp]=v
low[tmp]=graph[u][v];
if(low[tmp-1]<low[tmp])
low[tmp]=low[tmp-1];
if(v==n)
{//找到一条增广路
maxflow+=low[tmp];
for(u=0u<tmp;u++)
{//改变残留网络
front = q[u];
rear = q[u+1];
graph[front][rear] -= low[tmp];
graph[rear][front] += low[tmp];
}
tmp=0
}
}
}
}
int main(void)
{
freopen(“milk6.in”,“r”,stdin);
freopen(“milk6.out”,“w”,stdout);
int i
long long s,e,c
long long u,v,front,rear
int used[36];
scanf(“%d%d”,n,&m);
memset(graph,0,sizeof(graph));
for(i=0i<m;i++)
{
scanf(“%lld%lld%lld”,s,&e,&c);
graph[s][e] += 1001c+1
se[i][0]=s;
se[i][1]=e
se[i][2]=c1001+1//这里必须是1001c+1不然可能会出现输出不在割边里面的边
}
sap();
memset(used,0,sizeof(used));
d[rear=0]=1
front=-1
used[1]=1
while(front<rear)
{
u=d[++front];
for(v=1v<=n;v++)
{
if(0 == used[v]& graph[u][v] > 0)
{
d[++rear]=v
used[v]=1
}
}
}
front=maxflow//这个记录当前最大流是为了后面求割边集
u = maxflow/1001//原图最大流
v = maxflow-1001u//割边集的大小
maxflow=u
printf(“%lld %lld\n,maxflow,v);
for(u=0u<m&v;u++)
{
memset(graph,0,sizeof(graph));
for(i=0i<m;i++)
{
graph[se[i][0]][se[i][1]]+=se[i][2];
}
graph[se[u][0]][se[u][1]] -= se[u][2];
sap();
if(se[u][2]+maxflow==front)
{
printf(“%lld\n,u+1);
v
}
}
return 0
}

2011-03-14
USACO 4.3.4 Letter Game

中文题目
这题看清两点,一是每个单词的长度从3-7不等,二是不一定要把原字符串分割完全.注意这两点之后就好办了.我的做法是用一个数组asn[][]记录所有的分割情况,不管是分割了一次还是分割了两次.ans[i][0]表示分割了几次,如果是1的话那么还可以分割一次,如果是2的话,那么剩下的就不可以背分割了,ans[i][1]只有在ans[i][0]==1的情况下才有意义,意义是接下来的这个字符串的长度.这样便于第二次分割时的查找,然后每次从lgame.dict中读入一个字符串,就把ans数组检查一次,而且还把原字符串检查一次,如果产生新的可能符合情况的字符串就加入到ans数组中,这样处理完之后,所有的结果就都在ans数组中了,接下来的事情就是算得分了,用一个数组记录每个字符串的得分,比较得到最大值,再把所有和最大值一样的字符串组复制到一个输出数组中[因为要排序,但是ans数组中的字符串是没有排过序的].最后输出就行了.
代码如下:

/
ID:qcx97811
LANG:C
TASK:lgame
/
#include
#include
#include
#include

char str[12],tmp[12];
int str_len,tmp_len,idx//str_len是input的长度 tmp_len是每次从lgame.dict中读取的长度
//idx是ans的最大下标
char val[28]={2,5,4,4,1,6,5,5,1,7,6,3,5,2,3,5,7,2,1,2,4,6,6,7,5,7};//每个字符的value
char ans[5006][20],pri[102][16];//ans存可能的结果 pri存结果并排序
void output()
{
char ans_val[5006];
int i,j,k,max
int seg
max=0
memset(ans_val,0,sizeof(ans_val));
//计算value值
for(i=0i<idx;i++)
{
if(1 == ans[i][0])
{//一个部分
for(j=0j<ans[i][1];j++)
{
ans_val[i]+=val[ans[i][j+2]-‘a’];
}
}
else
{//两个部分
for(j=2‘\0’ != ans[i][j];j++)
{
if(‘ ‘ == ans[i][j])
continue
k=ans[i][j]-‘a’
ans_val[i]+=val[k];
}
}
if(max<ans_val[i])
max=ans_val[i];
}
printf(“%d\n,max);
seg=0//把所有value==max的都复制到pri数组中 并排序
for(i=0i<idx;i++)
{
if(ans_val[i]==max)
{
if(1 == ans[i][0])
{
for(j=0j<ans[i][1];j++)
pri[seg][j]=ans[i][j+2];
pri[seg][j]=‘\0’
}
else
{
for(j=2‘\0’ != ans[i][j];j++)
pri[seg][j-2]=ans[i][j];
pri[seg][j]=‘\0’
}
seg++
}
}
//排序
#if 1
for(i=0i<seg-1;i++)
{
k=i
for(j=seg-1j>;i;j)
{
if(strcmp(pri[k],pri[j])>0)
{
k=j
}
}
if(k!=i)
{
j=0
do
{
ans_val[j]=pri[i][j];
j++
}while(ans_val[j]!=‘\0’);
j=0
do
{
pri[i][j]=pri[k][j];
j++
}while(pri[i][j]!=‘\0’);
j=0
do
{
pri[k][j]=ans_val[j];
j++
}while(pri[k][j]!=‘\0’);
}
}
#endif
//最后输出
for(i=0i<seg;i++)
{
j=0
while(pri[i][j] != ‘\0’)
{
printf(“%c”,pri[i][j]);
j++
}
printf(\n);
}
}
void print()
{//用于调试
int i
printf(“——-print——-\n);
for(i=0i<idx;i++)
printf(“%d::%d::%s\n,ans[i][0],ans[i][1],ans[i]+2);
printf(“——-print——-\n);
}
int main(void)
{
freopen(“lgame.in”,“r”,stdin);
freopen(“lgame.out”,“w”,stdout);
int i,j,k
char f
char used[16];
scanf(“%s”,str);
str_len=strlen(str);
freopen(“lgame.dict”,“r”,stdin);
while(1)
{
scanf(“%s”,tmp);
if(‘.’ == tmp[0])
break
tmp_len=strlen(tmp);
memset(used,0,sizeof(used));
//首先从原字符串找
for(i=0i<tmp_len;i++)
{
for(j=0j<str_len;j++)
{
if(0==used[j]&str[j]==tmp[i])
{//str[j] == tmp[i]
used[j]=1
break
}
}
if(j==str_len)//find a char equals with tmp[i]
break
}
if(i==tmp_len)
{//all the char can be found in str
ans[idx][0]=1
ans[idx][1]=tmp_len
for(i=0i<tmp_len;i++)
{
ans[idx][i+2]=tmp[i];
}
for(i=tmp_len+2,j=0j<str_len;j++)
{
if(0==used[j])
ans[idx][i++]=str[j];
}
ans[idx][i]=‘\0’
idx++
}
//接下来从那些还只被分了一份的里面找
for(j=0j<idx;j++)
{
memset(used,0,sizeof(used));
if(ans[j][0]>1)
continue
for(i=0i<tmp_len;i++)
{
for(k=ans[j][1]+2k<str_len+2;k++)
{
if(0==used[k]&tmp[i]==ans[j][k])
{
used[k]=1
break
}
}
if(k==(str_len+2))
{
break
}
}
if(i==tmp_len)
{
ans[idx][0]=2//标志 表示已被分割了两次
ans[idx][1]=2//这句可不加
for(i=2i<ans[j][1]+2;i++)
{
ans[idx][i]=ans[j][i];
}
ans[idx][ans[j][1]+2]=‘ ‘//在两部分之间加上一个空格 用于排序和输出
for(i=ans[j][1]+3,k=0k<tmp_len;k++)
{
ans[idx][i++]=tmp[k];
}
ans[idx][i]=‘\0’
idx++
}
}
}
output();
#if 0
print();
#endif
return 0
}

2011-03-07
USACO 4.3.3 Street Race

中文题目

对于第一问可以枚举每个点,如果没有这个点看能不能从0到N,如果能就说明这个点不是unavoidable点,这样的复杂度是定点数*变数,然后对于第二问的话,我们可以从第一问的答案里面再枚举,也就是说,如果是第一问的答案才有可能成为第二问的答案,这样的话,枚举第二问的时候只要考虑一下,split点一定是一个的起点,另一个的终点,然后没重边,然后不能有边从一个区域到另一个区域,终点的出度为0.其他的就没什么了.

代码如下:

/
ID:qcx97811
LANG:C
TASK:race3
/
#include
#include
#include
#include

int v,e
int graph[56][56],used[56];//graph表示原图
void bfs(int s,int n)
{//bfs搜索起点为s不经过n点的所有点,这里可以不传n
//直接used[n]=1就行了
int rear,front,i,j
int q[56];
memset(used,0,sizeof(used));
q[rear=0]=s;
used[0]=1
front=-1
while(front<rear)
{
i=q[++front];
for(j=0j<v;j++)
{
if(j != n & 0==used[j]&&graph[i][j]>0)
{
q[++rear]=j
used[j]=1
}
}
}
}
void work()
{
int i,ans[56],bans[56],j,k//ans是第一问的答案 bans是第二问的答案
int sum=0,bsum=0//sum是第一问的答案个数 bsum是第二问的答案个数
int f
for(i=0i<v-1;i++)
{
bfs(0,i);
if(0==used[v-1])
{//如果不能到达终点的话说明这个点是unavoidable点
ans[sum]=i
sum++
}
}
printf(“%d”,sum);
for(i=0i<sum;i++)
printf(“ %d”,ans[i]);
printf(\n);
for(i=0i<sum;i++)
{//枚举第一问中的点
f=1
bfs(0,ans[i]);
for(j=0j<v & f;j++)
{
if(1 == used[j])
{
for(k=0k<v & f;k++)
{
if(k != ans[i] & 0 == used[k] && graph[j][k]>0)
{
f=0
}
if(1==used[k] & graph[ans[i]][k]>0)
f=0 //终点的出度必须为0
}
}
}
used[ans[i]]=1
for(j=0j<v&f;j++)
{
if(0 == used[j] & ans[i]!=j)
{
for(k=0k<v&f;k++)
{
if(k != ans[i] & 1 == used[k] && graph[j][k] > 0)
f=0
}
}
}
if(1 == f)
{
bans[bsum++]=ans[i];
}
}
printf(“%d”,bsum);
for(i=0i<bsum;i++)
printf(“ %d”,bans[i]);
printf(\n);
}
int main(void)
{
freopen(“race3.in”,“r”,stdin);
freopen(“race3.out”,“w”,stdout);
int i,j
v=e=0
memset(graph,-1,sizeof(graph));
while(1)
{
scanf(“%d”,i);
if(-1 == i)
break
while(-2 != i)
{
graph[v][i]=1
scanf(“%d”,i);
}
v++
}
#if 0
for(i=0;i
{
for(j=0;j
printf(“%d “,graph[i][j]);
printf(“\n”);
}
#endif
work();
return 0
}

2011-03-06
USACO 4.3.2 The Primes

这题直接搜就行了,不过要注意搜索顺序,这里如果选的不好的话,那么基本就不可能过了,一开始我选的是先确定第一行再确定反对角线,然后再依次确定第二行,第三行和第四行,再确定第2列最后确定最后一行,这样的顺序我主要是考虑可以比较好的算出一些东西,也就是可以少算一点东西[因为一开始我是用的最原始的一行一行的搜索],可是这样不行,发现会死在第4组数据上,给的是2s我的用了2.67s.无奈之下搜了解题报告,原来可以先确定两条对角线,因为它们两影响的最多,我们把最复杂的先做了,那么剪枝也可以在一开始就实现,这样可以节约不少时间,这样之后就过了,后来的搜索顺序是先对角线—>反对角线—->第一行—->第二列—>第四列[这里可以顺便算出第五行]—>第一列[这里可以顺便算出第三行的第五个]—>第二行[剩下的都可以顺便算出来了]代码写了250+行,就不在这里贴了,放在这里,有兴趣的可以看看.另外官方的解题报告和这个差不多,不过还多加了一个用对称来减少搜索的时间,官方的解题报告传在这里,有兴趣的可以下来看看

2011-02-26
usaco 4.3.1 buy low,buy lower

题意

首先这题的第一问是很简单的,学过dp的应该就不会有问题了,虽然有O(n*lgn)的算法,但是这里还是用O(n^2)的比较好一点,因为还有第二问,对于第二问我是这么想的,用如下序列来说明,9 8 7 10 9 7 我在原序列之后加上一个0,这样的话只需要得到最后这个0的信息就是我们要求的值了.我们可以用ans表示每一个数据的最大下降子序列的长度,另外用num表示原数据,f表示方案数,最后还有一个数组used表示是否在算f时这个值已经用过[这里的值是原数据]然后可以得到上面的数据的一些信息如下

num 9 8 7 10 9 7

ans 1 2 3 1 2 3

f 1 1 1 1 1 2

这里我们没有用到used数组,但是待会的程序中就有用了,首先我们可以得到所有的ans值,然后这里的f我们是根据前面的某些值得到的,如果ans[j]+1>ansi那么f[i]就由f[j]得来,但是可能有多个这样的情况:ans[j]+1==ansi这里怎么解决呢?这里我们会发现如果对这些j中,如果某两个j对应的num值不同的话,那么f[i]肯定就是这两个f值的和,因为他们产生的序列肯定是不会一样的,但是如果某两个j对应的num相同的话,我们怎么办呢?这里我们只需考虑后面那个j就行了,因为后面那个j会覆盖前面那个j的所有信息,假设后面那个j的下标是j1后面那个是j2那么ans[j2]>=ans[j1]肯定成立,同时f[j2]>=f[j1]也成立,这里很明显吧,因为我们如果把j1到j2中间的那些数据去掉的话那么就是取相等的,如果中间再加入一个数到下降子序列里面的话,那么就是取>了.理解了这些之后我们可以得到如下的代码 for i=1 i <= n;i++ for j=i-1;j>=0;j– if num[j] > num[i] if ans[j]+1 > ans[i] ans[i]=ans[j]+1; f[i]=f[j]; memset(num,0,sizeof(num)); used[num[j]]=1;//这里就用到了上面的只取后面那个,因为后面这个已经把前面那个的信息给覆盖了 else if ans[j]+1 == ans[i] & 0 == used[num[j]] f[i] += f[j]; used[num[j]]=1; 这样之后输出的答案就是ans[n]-1和f[n]了,不过这里得用高精度具体代码如下:

/
ID:qcx97811
LANG:C
PROG:buylow
/
#include
#include
#include

int N;
int ans[5006],num[5006],front[5006][100];
int used[20006];

void add(int a[],int b[])
{//高精度加法 结果存在a数组中
int len,i
if(a[0] > b[0])
len = a[0];
else
len = b[0];
for(i = a[0]+1i < 100;i++)
a[i]=0//清0后面的数据
for(i = b[0]+1i < 100;i++)
b[i]=0//清0后面的数据
for(i = 1i <= len;i++)
{
a[i] += b[i];
a[i+1] += a[i]/10
a[i] %= 10
}
if(0 != a[len+1])
a[0] = len+1
else
a[0] = len
return
}
int main(void)
{
freopen(“buylow.in”,“r”,stdin);
freopen(“buylow.out”,“w”,stdout);
int i,j,k
int len
scanf(“%d”,N);
for(i = 0i < N;i++)
{
scanf(“%d”,num[i]);
}
num[N]=0
ans[0] = 1
front[0][0] = 1
front[0][1] = 1
for(i = 1i <= N;i++)
{
ans[i] = 1
memset(front[i],0,sizeof(front[i]));
memset(used,0,sizeof(used));
for(j = i-1j >;= 0;j)
{
if(num[j] > num[i])
{
if(ans[i]<ans[j]+1)
{
ans[i] = ans[j]+1
for(k = 0k <= front[j][0];k++)
{
front[i][k] = front[j][k];
}
for(k = front[i][0]+1k < 100;k++)
front[i][k]=0
memset(used,0,sizeof(used));
used[num[j]]=1
}
else
{
if((ans[j]+1==ans[i]) & (0 == used[num[j]]))
{
add(front[i],front[j]);
used[num[j]]=1
}
}
}
}
if(0 == front[i][0])
{
front[i][1]=1
front[i][0]=1
}
}
printf(“%d “,ans[N]-1);
for(i = front[N][0];i >= 1;i)
printf(“%d”,front[N][i]);
printf(\n);
return 0
}

2011-02-21
usaco 4.2.4 cowcycle

这题数据不是很BT,用简单的dfs就可以过,不过还是有几点要注意的.我就是死在其中的某点上.
1.我一开始自作聪明的加了个剪枝,可是结果是越剪时间用的越多,我的剪枝方法是,确定前轮之后[我先确定前轮,因为我觉得这样比先确定后轮时间要少一点]然后再用那个3倍关系确定后轮的范围,这样时间用的更多.真是画蛇添足了
2.我用的排序时qsort,由于一直用c写acm的代码,排序基本是qsort,一般是没问题的,可是这次就死在这里.后来自己写的冒泡就过了,才知道qsort其实不是非常快,尤其是小数据的时候.
其他的应该只要读懂题意,然后照着题目的要求算方差就OK了,千万别搞错了differences的个数
代码如下:

/
ID:qcx97811
LANG:C
TASK:cowcycle
/
#include
#include
#include
#include

int F,R,F1,F2,R1,R2
int amax,bmax,amin,bmin//amax amin是前轮的最小和最大值 bmin和bmax是后轮的最小和最大值
int a[10],b[12],aa[10],bb[12];//a记录本次的前轮数据 b本次的后轮数据 aa和bb是最优的前轮和

后轮数据
double diff[56],mean,var,best//diff和题中的有点不同

void dfsb(int now,int beg)
{
int i,j
double k
if(R == now)//后轮选完了
{
if(a[0]3b[0] > a[F-1]b[R-1])//the 3X rule
return ;
for(i = 0i < F;i++)
{
for(j = 0j < R;j++)
{//calc the diff
diff[Ri+j] = a[i]1.0/(b[j]

1.0);
}
}
for(i = 0i < FR-1;i++)
{//冒泡排序
for(j = FR-1j >; i;j)
{
if(diff[j] > diff[j-1])
{
k = diff[j];
diff[j] = diff[j-1];
diff[j-1] = k
}
}
}
mean = (diff[0] - diff[RF-1])/(RF-1);//the num of the

differences is RF-1 计算平均值
var = 0
j = RF-1
for(i = 0i < j;i++)
{
var += (diff[i]-diff[i+1]-mean)(diff[i]-diff

[i+1]-mean);
}
var = var1.0/(RF-1);//计算方差
if(-1 == aa[0])//如果是第一次的话
{
for(i = 0i < F;i++)
aa[i] = a[i];
for(j = 0j < R;j++)
bb[i] = b[i];
best = var
}
else
{
if(var < best)
{//如果更优的话
best = var
for(i = 0i < F;i++)
aa[i] = a[i];
for(i = 0i < R;i++)
bb[i] = b[i];
}
}
return ;
}
if(beg > bmax)
return ;//没后轮选了
for(i = begi <= bmax;i++)
{//选下一个后轮
b[now] = i
dfsb(now+1,i+1);
}
}
void dfsa(int now,int beg)
{
int i,j,k,kk
if(F == now)
{//前轮选完了
if(a[0]3R1 > a[F-1]R2)
return//3x规则
dfsb(0,R1);//开始选后轮
return ;
}
if(beg > amax)
return ;//没前轮选了
for(i = begi <= amax;i++)
{//测试当前的前轮 然后开始选下一个前轮
a[now] = i
dfsa(now+1,i+1);
}
}

int main(void)
{
freopen(“cowcycle.in”,“r”,stdin);
freopen(“cowcycle.out”,“w”,stdout);
int i,j
scanf(“%d%d”,F,&R);
scanf(“%d%d%d%d”,F1,&F2,&R1,&R2);
amin = F1
amax = F2
bmax = R2
bmin = R1
aa[0] = -1//标记
dfsa(0,amin);//开始搜索
printf(“%d”,aa[0]);
//下面是输出
for(i = 1i < F;i++)
printf(“ %d”,aa[i]);
printf(\n%d”,bb[0]);
for(i = 1i < R;i++)
printf(“ %d”,bb[i]);
printf(\n);
return 0
}

2011-02-12
USACO 4.2.3 Job processing

题意

对于第一问,比较容易想到.直接贪心就可以了,也就是每次都只处理一个任务,每次取当前结束时间最靠前的一个,这样的话,就可以保证总的结束时间一定是最早的.比如说5 2 3 1 1 3 1 4的话,那么一共会循环5次[也就是5个任务],第一次选第一台机器,因为它的结束时间是1,然后它的结束时间就会变成2[这里是指如果这个任务让这台机器来完成,那么完成之后的结束时间],第二次就会选第2台机器,因为第二台机器的结束时间还是1,依次类推,完成A任务的时间就会是1 1 2 2 3也就是一共需要3个单位的时间这是第一问的答案.那么第二问的答案就比这个要稍微难想一点,不过我们知道A B两项任务是没关系的,也就是进水不犯河水,各干各的.而且对于完成每个任务的每种机器也是各干各的,互不干扰.还有一点就是我们可以想象如果把完成A任务的和完成B任务的所需时间一个按从小到大排序,一个从大到小排序,然后对应的相加,也就是说完成A任务最早的放到B那就让它最晚完成,这样总的结束时间就会早一点.但是这里有个问题就是这样可以吗,因为B任务的开始是以A任务的结束为开始的,如果B任务那样一搞,但是A那某个还没完成咋办呢?这样我们来看看一个简单的分析,就那上面的例子来说,那么排序之后会是这样的
1 1 2 2 3
4 3 3 2 1[单独完成B任务所需的时间]这里还得说一点,就是这个时间是可以”换”的,也就是不一定要特定的任务在特定的机器上完成,反正就是里面的2和3 或者3和4之类的不是指的某个任务在第几个单位时间内完成,而是说最好的安排是有任务在第1个单位完成,有任务在第4个单位完成,这就OK了.
那么我们的第二问就是这样排列之后上下两个相加,然后取这些和的最大值.这里是5.但是就会有这样的疑问,也就是说下面那一排是首先不管A的,那么又没有可能是某个时候和下面对应的那个上面的任务还没问成呢?这样不是就不对了么?这里我们可以这样考虑,因为对于B中不同的机器之间是不存在这样的问题的,只有对于同一类机器,可是说同一台机器才会有这样的问题,因为不同机器是互不干扰的,那么我们单独考虑一台机器[B机器]
如果我们有如下的情况
1 3 6
6 4 2[这里是说明这台机器完成一件任务需要2分钟]
那么我们得到的结果应该是8[=2+6],那么第1分钟的时候第一件A任务完成了,现在我们可以让B的机器去做它,到了第3分钟刚好完成了,那么我们让它继续做第二件A任务,到了第5分钟的时候完成了,可是现在没有A任务给它,好的,这样更好,因为这样不会有我们认为的那种”忙不过来的”感觉.最终第6分钟来任务了,在第8分钟结束.
好了看看下面的一组数据
1 4 6
9 6 3
这里的数据是第1分钟B机器接到任务,然后第4分钟完成了,然后刚好接到第二个任务,继续做,到了第6分钟的时候,还没做完,怎么办?继续做原来的任务,这样就在第7分钟开始做等在那得第三个任务,可是这是不是一个巧合呢?下面就是见证奇迹的时候- -.其实这不是什么巧合,而是事实.你可以这样想,反正B任务得工作9个单位时间,这两个例子里面是不是都工作了9个单位时间呢?对啊,没错啊.可是还是有点糊涂,那么你可以把第一行的后一个减前一个得到一个差,这样就会得到另外一个数列,如下
3 2
这里要干嘛呢?你可以这样想,如果要是出现前面那种情况,那么后面的和会比较大[8比前面的大,这个原因就是上面的数列决定的]如果要是第二个例子的话,那么后面的结果不会比前面的大,这样只需要知道放在这台机器上工作的A任务的第一个任务的完成时间然后再加上一个几个任务*每个任务的时间久OK了.这样每台机器的搞清楚了,因为不同机器互不干扰,所以这样就是最佳答案了.

代码如下:

/
ID:qcx97811
LANG:C
TASK:job
/
#include
#include
#include
typedef struct
{
int end
int cost
}Node

Node aMachine[36],bMachine[36];
int N,A,B;
int aEnd[1006],bEnd[1006];
int total

int cmp(const void a,const void b)
{
Node c = (Node )a
Node d = (Node )b;
if(c->end == d->end)
return 0
if(c->end > d->end)
return 1
return -1
}

void work()
{
int tn,k,i
tn = N;
memset(aEnd,0,sizeof(aEnd));
i = 0
while(tn)
{//每次减少一个任务
qsort(aMachine,A,sizeof(aMachine[0]),cmp);//对结束时间排序
tn
aEnd[i] = aMachine[0].end
aMachine[0].end += aMachine[0].cost//更改当前的结束时间
i++
}
#if 0
for(i = 0;i < N;i++)
printf(“%d\n”,aEnd[i]);
#endif
printf(“%d”,aEnd[N-1]);//这个是A Machine工作完所需的时间
tn = N;
i = 0
while(tn)
{
qsort(bMachine,B,sizeof(bMachine[0]),cmp);
tn
bEnd[i] = bMachine[0].end
bMachine[0].end += bMachine[0].cost
i++
}
#if 0
printf(“\n”);
for(i = 0;i < N;i++)
printf(“####%d####\n”,bEnd[i]);
#endif
tn = aEnd[0]+bEnd[N-1];
for(i = 0i < N;i++)
{
if(aEnd[i] + bEnd[N-1-i] > tn)
tn = aEnd[i] + bEnd[N-1-i];
}
printf(“ %d\n,tn);
}

void input(Node in[],int num)
{
int i
for(i = 0i < num;i++)
{
scanf(“%d”,in[i].cost);
in[i].end = in[i].cost
}
}
int main(void)
{
freopen(“job.in”,“r”,stdin);
freopen(“job.out”,“w”,stdout);
int i
scanf(“%d%d%d”,N,&A,&B);
input(aMachine,A);
input(bMachine,B);
work();
return 0
}

2011-02-11
USACO 4-2-2 The Perfect Stall --网络流dinic算法

题意

利用这题学习了下dinic.题意就不说了,很容易理解的一题

以前网络流的算法一直只懂最白痴的EK,后来大家说sap是万能的,于是就想学学sap,可是找了些资料之后发现我先学会的是dinic.下面说说我的理解吧.如有错误还请指出.
首先说明下层次图的概念:对原图的每一个点设置一个层次,这个新图就成了所谓的层次图了.然后允许弧就是层次图中有边且原图中也有边的弧.
dinic就是利用层次图,然后每次找增广路径的时候就只走允许弧,如果单纯这样的话,个人认为和EK算法还是差不了多少的,毕竟dinic也是多次bfs然后再dfs找增广路,那我不还如EK呢,何况EK还简单不易写错.dinic的精华应该是退栈,也就是dfs找到一条增广路之后,并不是再从源点开始找一次,而是退到从源点可达的最远一个点[这样说来很抽象]比如下面的例子
ab = 10 bc = 5 cd = 5 bf=5 fd=5 de=10[abcdef是顶点]
那么源点是a汇点是f的话
栈中情况是a->ab->abc->abcd->abcde–增广—然后退到b因为b是栈中a现在能够到达的最远的顶点了.现在从b开始增广就会出现时ab->abf->abfd->abfde—增广也就是dinic的精华在这里;具体的大家可以看2007年王上欣的论文<浅谈基于分层思想的网络流算法>
下面给出我的一份代码,经供参考

/
ID:qcx97811
LANG:C
TASK:stall4
/
#include
#include
#include
#include

int N,M,maxflow//N和M是题目中的意思 maxflow就是最大流的值
int graph[406][406],pre[406],d[406];//graph是图 pre是每个节点的前驱 d表示每个节点的层次

int outdegree(int now)
{//返回传入顶点的出度包括在层次图中的信息
int i,out
out = 0//out代表传入顶点的出度
for(i = 0i <= (N+M+1);i++)
if(((d[now] + 1) == d[i]) & graph[now][i] > 0)
{//这里用break是因为只需要知道出度是否为0 不需要知道度为多少
out++
break
}
return out
}
int dinic()
{
int rear,front,u,out,i,top,add
int q[406];
maxflow = 0
while(1)
{
//通过bfs重构层次图
memset(d,-1,sizeof(d));
memset(pre,-1,sizeof(pre));
d[0] = pre[0] = 0//这里pre数组相当于一个bool数组记录某个顶点是否被用
rear = front = -1
rear++
q[rear] = 0
while(front < rear)
{//bfs构建层次图
u = q[++front];
for(i = 0i <= (N+M+1);i++)
{
if(-1 == pre[i] & graph[u][i] > 0)
{//如果这个点没有被用而且残留网络中有边
pre[i] = u//记录当前顶点已经被用
d[i] = d[u] + 1//层次加1
rear++//入队
q[rear] = i
}
}
}

    <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">-</span><span style="color: #add8e6;">1</span> <span style="color: #f5deb3;">==</span> <span style="color: #f5deb3;">pre</span><span style="color: #f5deb3;">[</span>N<span style="color: #f5deb3;">+</span><span style="color: #f5deb3;">M</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">])</span>
        <span style="font-weight: bold; color: #b0c4de;">break</span><span style="color: #da70d6;">//如果汇点不在层次图中标明已无增广路径</span>

    <span style="color: #f5deb3;">out</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">outdegree</span>(<span style="color: #add8e6;">0</span>);

    <span style="color: #f5deb3;">top</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span>
    <span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">top</span><span style="color: #f5deb3;">]</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span><span style="color: #da70d6;">//这里的q是用来记录增广路径上的点</span>
    <span style="font-weight: bold; color: #b0c4de;">while</span>(<span style="color: #f5deb3;">out</span>)<span style="color: #da70d6;">//循环直到源点的出度为0</span>
        <span style="color: #f5deb3;">{</span>
            <span style="color: #f5deb3;">u</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">top</span><span style="color: #f5deb3;">];</span><span style="color: #da70d6;">//取栈顶元素</span>
            <span style="font-weight: bold; color: #b0c4de;">if</span>((N<span style="color: #f5deb3;">+</span><span style="color: #f5deb3;">M</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span>) <span style="color: #f5deb3;">==</span> <span style="color: #f5deb3;">u</span>)<span style="color: #da70d6;">//如果已经找到一条增广路径</span>
                <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//增广 然后队列回退到从源点可达的最远点</span>
                    <span style="color: #f5deb3;">add</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">INT_MAX</span>
                    <span style="font-weight: bold; color: #b0c4de;">for</span>(<span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span><span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;"><</span> <span style="color: #f5deb3;">top</span>;<span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">++</span>)
                        <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//判定本次可增广的流量</span>
                            <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]][</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">]]</span> <span style="color: #f5deb3;"><</span> <span style="color: #f5deb3;">add</span>)
                                <span style="color: #f5deb3;">{</span>
                                    <span style="color: #f5deb3;">add</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]][</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">]];</span>
                                <span style="color: #f5deb3;">}</span>
                        <span style="color: #f5deb3;">}</span>   
                    <span style="font-weight: bold; color: #b0c4de;">for</span>(<span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span><span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;"><</span> <span style="color: #f5deb3;">top</span>;<span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">++</span>)
                        <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//更新残留网络</span>
                            <span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]][</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">]]</span> <span style="color: #f5deb3;">-=</span> <span style="color: #f5deb3;">add</span>
                            <span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">]][</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]]</span> <span style="color: #f5deb3;">+=</span> <span style="color: #f5deb3;">add</span>
                        <span style="color: #f5deb3;">}</span>
                    <span style="color: #f5deb3;">maxflow</span> <span style="color: #f5deb3;">+=</span> <span style="color: #f5deb3;">add</span><span style="color: #da70d6;">//增加网络流量</span>
                    <span style="color: #da70d6;">//下面回退到从源点可达的最远的一个点</span>
                    <span style="font-weight: bold; color: #b0c4de;">for</span>(<span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span><span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;"><=</span> <span style="color: #f5deb3;">top</span>;<span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">++</span>)
                        <span style="color: #f5deb3;">{</span>
                            <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">outdegree</span>(<span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">])</span> <span style="color: #f5deb3;">==</span> <span style="color: #add8e6;">0</span>)
                                <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//这里不应该只考虑出度还应该考虑和q中的下一个元素是否有边(包括层次图和残留网络)</span>
                                    <span style="color: #f5deb3;">top</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">-</span><span style="color: #add8e6;">1</span><span style="color: #da70d6;">//这个地方如果出现top=-1应该也没问题的 因为这样的话out已经为0了</span>
                                    <span style="font-weight: bold; color: #b0c4de;">break</span>
                                <span style="color: #f5deb3;">}</span>
                            <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]][</span><span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span><span style="color: #f5deb3;">]]</span> <span style="color: #f5deb3;"><=</span> <span style="color: #add8e6;">0</span>)
                                <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//这个是防止某个点出度不为0但是q中这个点和下一个点的边已经为0了 那么就会一直死循环在里面这个while里</span>
                                    <span style="color: #f5deb3;">top</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">i</span>
                                    <span style="font-weight: bold; color: #b0c4de;">break</span>
                                <span style="color: #f5deb3;">}</span>
                        <span style="color: #f5deb3;">}</span>
                <span style="color: #f5deb3;">}</span>
            <span style="font-weight: bold; color: #b0c4de;">else</span>
                <span style="color: #f5deb3;">{</span>
                    <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">outdegree</span>(<span style="color: #f5deb3;">u</span>) <span style="color: #f5deb3;">></span> <span style="color: #add8e6;">0</span>)
                        <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//该点的出度不为0 则改变队列 把当前顶点入队这里的出度包括层次图的信息</span>
                            <span style="font-weight: bold; color: #b0c4de;">for</span>(<span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;">=</span> <span style="color: #add8e6;">0</span><span style="color: #f5deb3;">i</span> <span style="color: #f5deb3;"><=</span> (N<span style="color: #f5deb3;">+</span><span style="color: #f5deb3;">M</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span>);<span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">++</span>)
                                <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//寻找u顶点的下一个顶点</span>
                                    <span style="font-weight: bold; color: #b0c4de;">if</span>(<span style="color: #f5deb3;">d</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">u</span><span style="color: #f5deb3;">]</span><span style="color: #f5deb3;">+</span><span style="color: #add8e6;">1</span> <span style="color: #f5deb3;">==</span> <span style="color: #f5deb3;">d</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]</span> <span style="color: #f5deb3;">&amp;</span> <span style="color: #f5deb3;">graph</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">u</span><span style="color: #f5deb3;">][</span><span style="color: #f5deb3;">i</span><span style="color: #f5deb3;">]</span> <span style="color: #f5deb3;">></span> <span style="color: #add8e6;">0</span>)
                                        <span style="color: #f5deb3;">{</span>
                                            <span style="color: #f5deb3;">top</span><span style="color: #f5deb3;">++</span><span style="color: #da70d6;">//入栈</span>
                                            <span style="color: #f5deb3;">q</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">top</span><span style="color: #f5deb3;">]</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">i</span>
                                            <span style="font-weight: bold; color: #b0c4de;">break</span>
                                        <span style="color: #f5deb3;">}</span>
                                <span style="color: #f5deb3;">}</span>
                        <span style="color: #f5deb3;">}</span>
                    <span style="font-weight: bold; color: #b0c4de;">else</span>
                        <span style="color: #f5deb3;">{</span><span style="color: #da70d6;">//弹出队列的最高顶点</span>
                            <span style="color: #f5deb3;">d</span><span style="color: #f5deb3;">[</span><span style="color: #f5deb3;">u</span><span style="color: #f5deb3;">]</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">-</span><span style="color: #add8e6;">1</span><span style="color: #da70d6;">//当前顶点从层次图中删除</span>
                            <span style="color: #f5deb3;">top</span><span style="color: #f5deb3;">--</span><span style="color: #da70d6;">//从栈中删除</span>
                        <span style="color: #f5deb3;">}</span>
                <span style="color: #f5deb3;">}</span>
            <span style="color: #f5deb3;">out</span> <span style="color: #f5deb3;">=</span> <span style="color: #f5deb3;">outdegree</span>(<span style="color: #add8e6;">0</span>);<span style="color: #da70d6;">//判定当前源点的出度</span>
        <span style="color: #f5deb3;">}</span>
<span style="color: #f5deb3;">}</span>

}

int main(void)
{
freopen(“stall4.in”,“r”,stdin);
freopen(“stall4.out”,“w”,stdout);
int i,j,ct,c
memset(graph,0,sizeof(graph));
scanf(“%d%d”,N,&M);
/下面是初始化图/
for(i = 1i <= N;i++)
{
scanf(“%d”,ct);
for(j = 0j < ct;j++)
{
scanf(“%d”,c);
graph[i][c+N] = 1
}
}
for(i = 1i <= N;i++)
graph[0][i] = 1
for(i = N+1i <= (N+M);i++)
graph[i][N+M+1] = 1
/上面是初始化图/
dinic();//调用dinic求最大流
printf(“%d\n,maxflow);//输出最大流
return 0
}

2011-02-10
USACO 4-2-1Drainage Ditches

题目翻译

一个入门的网络流题目,由于点和边都不多,所以我用了原始的EK算法(其实当时我也只会这最原始的算法),也就是每次用bfs找增广路,复杂度是O(V*E^2)。下面直接给出代码

/
LANG:C
TASK:ditch
ID:qcx97811
/
#include
#include
#include

int graph[206][206],pre[206];//graph是原图,pre是用来存每个点的前驱的
int N,M,maxflow//N和M是题中的 maxlfow就是结果了

int bfs()
{
int i,j
int q[206];
int front,rear
memset(pre,-1,sizeof(pre));
front = rear = -1
q[++rear] = 1
while(front < rear)//bfs找一条从源点到汇点的路径
{
i = q[++front];
for(j = 1j <= M;j++)
{
if(-1 == pre[j] & graph[i][j] > 0)
{//如果当前点没有没用而且可用
pre[j] = i
rear++
q[rear] = j
if(j == M)//如果已经到了汇点 也就是已经找到一条增广路径
return 1
}
}
}
return 0
}
void max_flow()
{
int i,j,add
maxflow = 0
while(0 != (add = bfs()))
{//如果还有增广路径
add = 10000006
for(i = Mi != 1;i = pre[i])
{//找出本次能增广的最大流量
j = pre[i];
if(graph[j][i] < add)
add = graph[j][i];
}
for(i = Mi != 1;i = pre[i])
{//改变残留网络
j = pre[i];
graph[j][i] -= add
graph[i][j] += add
}
maxflow += add//更改结果
}
}
int main(void)
{
freopen(“ditch.in”,“r”,stdin);
freopen(“ditch.out”,“w”,stdout);
int i,s,e,c
scanf(“%d%d”,N,&M);
memset(graph,0,sizeof(graph));
//下面是建图
for(i = 0i < N;i++)
{
scanf(“%d%d%d”,s,&e,&c);
graph[s][e] += c
}
max_flow();//调用max_flow得到结果
printf(“%d\n,maxflow);
return 0
}

2011-02-10
USACO 4-1-2 Fence Rails

题目翻译

这题一开始不知如何下手,后来参考了nocow和其他大牛的才写出来的.这里就给出nocow的分析再贴上代码,这题说是dfs-id算法,可是我怎么看都觉得是一般的dfs然后加剪枝.

nocow分析见这里

下面是我的代码:

/
ID:qcx97811
LANG:C
TASK:fence8
/
#include
#include

int board[56],rail[1026],rail_sum[1026];
int N,R,bsum,up

//排序用的模板
int cmp(const void a,const void b)
{
if((int )a > (int )b)
return 1
if((int )a == (int )b)
return 0
return -1
}

int work(int total,int rstart,int bstart)
{//total是到当前已经浪费掉的木板长度
//rstart更准确的是rend也就是当前的最大rail下标 因为是从大到小
//bstart是当前从哪块board开始的
int i
int t_bstart,t_total
t_total = 0
if(-1 == rstart)//表示搜索已经结束了
return 1
for(i = N-1i >;= bstart;i)
{//搜索 从大到小
if(board[i] >= rail[rstart])
{//如果可以从这个board上切的话
board[i] -= rail[rstart];//更新board
if(board[i] < rail[0])
{//如果这个board已经不可能再切出其他rail了
t_total = total+board[i];//更新浪费的board总数
if(t_total+rail_sum[up] > bsum)
{//如果已经不可能切出up+1[搜索的是下标]个rail
board[i] += rail[rstart];//回溯
continue//进行下次个搜索
}
}
else
t_total = total//浪费的board
if(rstart > 0 & (rail[rstart-1] == rail[rstart]))
t_bstart = i//如果下一块rail和当前的rail相等
//那么下一块rail所对应的board一定比当前rail所对应的
//board的下标要大 至少不会小
else
t_bstart = 0//board的最小下标为0 这里不用考虑某块board已经被用 因为每次都会更新board的大小
if(1 == work(t_total,rstart-1,t_bstart))
return 1//如果搜索成功的话 就返回成功
board[i] += rail[rstart];
}
}
return 0
}
int main(void)
{
freopen(“fence8.in”,“r”,stdin);
freopen(“fence8.out”,“w”,stdout);
int i
scanf(“%d”,N);//N是board的数目
bsum = 0//bsum用来记录所有board的总和 用于一个小剪枝
for(i = 0i < N;i++)
{
scanf(“%d”,board[i]);
bsum += board[i];
}
scanf(“%d”,R);//R是rail的的总数
for(i = 0i < R;i++)
{
scanf(“%d”,rail[i]);
}
qsort(board,N,sizeof(board[0]),cmp);
qsort(rail,R,sizeof(rail[0]),cmp);
//对board数组和rail数组进行从小到大的排序
//下面的rail_sum数组表示从rail[0]加到rail[i]的总和 也是用于剪枝
rail_sum[0] = rail[0];
for(i = 1i < R;i++)
{
rail_sum[i] = rail_sum[i-1] + rail[i];
}
up = R-1//up是有可能的最大下标
while(rail_sum[up] > bsum)
up
#if 0
用于调试
printf(“%d\n”,up);
#endif
while(0 == work(0,up,0))//搜索结果
up
printf(“%d\n,up+1);//由于搜索出来的是下标 所以结果得+1
return 0
}