终于做到的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;
}