做了道TOJ的题,不是很难。
怎么说呢,就是脑袋里有想法,但是代码就是写不出来….
功力还是不行啊

TOJ 69.Workload

有n份工作要分配给n个人来完成,每个人完成一份。第 i 个人完成第 k份工作所用的时间为一个正整数tik,其中1 ≤ i, k ≤ n。试确定一个分配方案,使得完成这n份工作的时间总和最小。

输入
输入包含n+1行。

第一行为一个正整数n。

第2行到第n+1行中每行都包含n个正整数,形成了一个n×n的矩阵。在该矩阵中,第 i 行第k列元素tik表示第 i 个人完成第 k件工作所要用的时间。

输出
一行,包含1个正整数,表示所有分配方案中最小的时间总和。

思考的时候脑袋里大概有这么些想法:
1.用一个二维数组记录时间,totalTime就是第一维下标各不相同和第二维下标各不相同的相加之和
比如: n = 3 的时候 可能就是
time1 + time[2][2] + time[3][3] //这里的第一个方括号打不出来 尴尬…
2.应该是一个人先挑一种工作,然后让下一个人,在剩余工作中再挑一个,这就需要一个isWorked的数组,
来表示各个工作是否已经被挑选掉,比如,0为未做,1为做了。
3.初始化时间花费cost为对角线之和 各种情况和cost比较 更新cost的值

想法是有了,然而想写二重循环来解决…可能是个二维数组的思维定势
于是就卡壳了…
后来找到一篇blog 看了之后感觉就是实现了我的想法…
[CSDN ACM典例之工作分配问题][2]
[2]: http://blog.csdn.net/f309587969/article/details/6338683

然后照着敲了一遍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<stdio.h>

int isWorked[16] = {0,};
int time[16][16] ;
int cost ;
// i表示工作的人 
void work(int i , int count,int n ){
    //如果i 超出了工作的人数上限 表示分配完成 并且count比原来cost花费少 则更新cost的值
  if( i > n && count < cost ){
      cost = count ;
        return ;
 }
    int j ;
  //回溯思想 
  if(count < cost)
  // j表示第几件工作 
 for( j = 1 ; j<= n;j++){
     //如果工作未被做 isWorked = 0  
     if(isWorked[j] == 0){
           isWorked[j] = 1;
          //工作交给i+1 并且把开关设为1 表示已经做掉 
           work( i+1,count+time[i][j],n);
            //出来之后 要进行重新分配 将isWorked[j]重设为 0
         isWorked[j] = 0;
      }
    }
}
int main(){
    int n ; 
 scanf("%d",&n);
 int i,j ;
    for(i = 1 ; i <= n ; i ++){
      for(j = 1 ; j <= n ; j++)
         scanf("%d",&time[i][j]);
        cost += time[i][i];
   }
    work(1,0,n); 
 printf("%d\n",cost);
    return 0 ;
}

关键就是这个work函数 递归的来实现了工作的分配
这应该就是我冥思苦想没想到的解决办法。

一道简单的题,暴露出水平还差得很。
不过不着急,慢慢来。

Categories:

Updated: