终于做到的C4,然而基础的不牢固致使C4做的这么艰难。基本上搀扶着做了这节的题,搜索剪枝啊,确实是门学问,而且搜索经常写做,得不出结果,郁闷。
Beef McNuggets (nuggets)
动态规划,需要做一下预处理,找两个最小的互质的数之积作为搜索上界。如果a,b互质,则ax+by=有>=a*b的整数解,这样就很快了。
Fence Rails (fence8)
参考了Qinz牛的blog,需要很多剪枝,这里用到了一个叫dfsid的迭代加深搜索算法,大意是dfs过程中如果求最短,就由浅至深增加深度直至找到解,此题是由深至浅,如果找到解就输出,否则深度减少。
dfsid伪代码如下:
DFSID
procedure dfs(depth:longint);
begin
if 要剪枝 then exit;
if 可行 then Print;
if Depth<MaxDepth then dfs(depth+1);
end;
procedure Iterative_Deepening;
begin
MaxDepth:=0;
while true do
begin
inc(MaxDepth);
dfs(1);
end;
end;
Fence Loops (fence6)
这题求最小环,我图论学的少,所以就搜索着做的,搜索的时候是两个方向,建立模型的时候有点儿技巧,没有什么剪枝就能过。
另外可以用dijkstra做,对每条边先去掉,求最短路径,再加上这条边,取最小值。
我觉得这个代码不错,把边转化成点做的,程序很简洁,分享代码:
Dijkstra
Dijkstra
#include <stdio.h>
#define MAX 30000
int n;
int len[101];
int map[2][101][8];
void pre(){
int i,j,k;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&j);
scanf("%d",&len[j]);
scanf("%d%d",&map[0][j][0],&map[1][j][0]);
for(k=1;k<=map[0][j][0];k++)scanf("%d",&map[0][j][k]);
for(k=1;k<=map[1][j][0];k++)scanf("%d",&map[1][j][k]);
}
}
int dis[101];
int isi[101];
int bef[101];
int dijkstra(int z){
int i,j,k;
for(i=1;i<=n;i++){dis[i]=MAX;isi[i]=0;}
for(i=1;i<=map[0][z][0];i++){bef[map[0][z][i]]=z;dis[map[0][z][i]]=len[z];}
while(1){
j=0;k=MAX;
for(i=1;i<=n;i++)
if(dis[i]<k && isi[i]==0){
j=i;
k=dis[i];
}
if(j==0)break;
if(j==z)return dis[z];
isi[j]=1;
for(i=1;i<=map[0][j][0];i++)
if(map[0][j][i]==bef[j])break;
if(i==map[0][j][0]+1)k=0;
else k=1;
for(i=1;i<=map[k][j][0];i++){
if(dis[map[k][j][i]]>dis[j]+len[j]){
dis[map[k][j][i]]=dis[j]+len[j];
bef[map[k][j][i]]=j;
}
}
}
return MAX;
}
main(){
freopen("fence6.in","r",stdin);
freopen("fence6.out","w",stdout);
int i,j=MAX,k;
pre();
for(i=1;i<=n;i++){
k=dijkstra(i);
if(k<j)j=k;
}
printf("%d\n",j);
return 0;
}
Cryptcowgraphy (cryptcow)
又是搜索,这个就是看了别人的解题报告。
剪枝方案:
1.如果C O W出现的顺序不是C在最前面,W在最后面,剪掉。
2.如果除去C O W后字符串字母和原字符串不符,剪掉。
3.如果 C O W不是成对出现,剪掉
4.用ELFhash函数为出现的字符串判重。
ELFhash
int hasher(char *k){
unsigned long h=0,g;
while(*k){
h=(h<<4)+*k++;
g=h &0xf0000000l; //7个0;
if(g) h^=g>>24;
h&=~g;
}
return h;
}