《训练指南》中的“突击战”和分金币问题

又到了周末,发现很堕落啊,眼看都星期天了,赶紧发一篇文章,总结一下上周学的。

原题见UVA11300,Spreading the wealth,和 UVA 11729 Commando War;先说突击战问题,关键问题是,一个任务要完成首先要先交代,然后再去执行,而且不能同时交代任务但可以同时执行各自的任务。经过简单的推理即可看出,显然是让执行时间长的任务先交代,这样所有任务执行的时间最短,思路简单,我就直接上代码了。

#include <iostream>
#include <cstdio>
#define M 1000

using namespace std;
struct node
{
    int Kjob;
    int Djob;
}Node[M];

int FindMax(int a[],int n)
{
    int max = a[0];
    int k = 0;
    for(int i = 1;i<n;++i)
    {
        if(a[i] > max)
        {
            max = a[i];
            k = i;
        }

    }
    return k;
}



int main()
{
    int n,test;
    int output[M] = {0};
    test = 0;
    int B[M],J[M];
    while(scanf("%d",&n) == 1 && n)
    {
        for(int i =0;i < n;++i)
        {
            scanf("%d%d",&Node[i].Kjob,&Node[i].Djob);
        }
        for(int i =0;i < n;++i)
        {
            B[i] = Node[i].Kjob;
            J[i] = Node[i].Djob;
        }
        int sum[M] = {0};
        int count = 0;
        for(int i =0;i< n;++i)
        {
            int m = FindMax(J,n);
            //J[m] = 0;
            count +=  B[m];
            sum[i] = count + J[m];
            J[m] = 0;
        }
        int l = FindMax(sum,n);
        output[test] = sum[l];
        ++test;
    }
    for(int i = 1;i<=test;++i)
    {
        cout << "case " << i << ":" << output[i-1] << endl;
    }
    return 0;
}
其实这道题的思路很直接,我写的程序也非常简单易懂,但有一点倒是很值得注意,就是, 当有多个数据相关联时,最好使用结构体这种很好的数据结构,效果很不错!


分金币问题,我耗费了很长时间也没有解出来,说实在话,我很讨厌环形结构,我记得USACO中也有一道相似的“项链问题”,题目我就不多说了,我刚开始的想法就是,先确定比平均数少的人数n,然后对整个数组遍历n次,就能找出最少的结果。然而,我尝试的结果显示,这样的值不是最小,我才发现,因为循环结构,才导致距离的相对性,因此不是能按顺序遍历就能得出结果的。之后我尝试了使用二维数组记录每个点到当前点的距离,结果很悲哀,没有结论!

#include <iostream>
#include <cstdio>
#include <cstdlib>

#define M 1000

using namespace std;
int arc[M][M];


int FindMin(int B[],int n)
{
    int min = B[0];
    int k = 0;
    for(int i =1;i<n;++i)
    {
        if(B[i] < min)
        {
            min = B[i];
            k = i;
        }
    }
    return k;
}

int MinDistance(int arc[][M],int divide[],int B[],int n,int k)
{
    int mark = 0;
    //int l =0;
    for(int j = 1;j<n && j!=k;++j)
    {
        int distancemin = arc[k][0];
        if(arc[k][j] < distancemin )
        {
            distancemin = arc[k][j];  //怎样记录数组中的两个最小的数的标号
            mark = j;
        }
    }
    if( Dvalue[k] < 0 && Dvalue[j] > 0 && (abs(Dvalue[k]) >=Dvalue[j])  )
    {
        B[k] += Dvalue[j];
        B[j] = average;
        Dvalue[k] += Dvalue[j];
        least += arc[k][j] * Dvalue[j];
        Dvalue[j] = 0;
    }
    if(Dvalue[k] < 0 && Dvalue[j] > 0 && abs(Dvalue[k]) < Dvalue[j])
    {
        B[k] = average;
        B[j] += Dvalue[k];
        Dvalue[j] += Dvalue[k];
        least += arc[k][j] * abs(Dvalue[k]);
        Dvalue[k] = 0;
    }




}
int main()
{
    int n;
    int average;
    int sum = 0;
    int counting  = 0;
    int B[M] = {0};
    while(scanf("%d",&n) == 1)
    {
        for(int i =0; i<n;++i)
        {
            cin  >> B[i];
            sum += B[i];
        }
        average = sum / n;
        for(int i =0;i<n;++i)
        {
            for(int j=0;j<n;++j)
            {
                if(j<= n/2)
                    arc[i][j] = j;
                else
                    arc[i][j] = n-j;
            }
        }
        for(int i =0;i<n;++i)
        {
            if(average > B[i])
                counting  +=1;
        }
        int Dvalue[M] = {0};
        for(int i =0;i<n;++i)
        {
            Dvalue[i] = B[i] - average;
        }
        int least = 0;
            /*
        //for(int i =0;i<counting ;++i)  //判断条件有问题,导致得到的不是最优解
        {
            int k= FindMin(B,n);
            for(int j =0;j<n;++j)
            {
                if( Dvalue[k] < 0 && Dvalue[j] > 0 && (abs(Dvalue[k]) >=Dvalue[j])  )
                {

                    B[k] += Dvalue[j];
                    B[j] = average;
                    Dvalue[k] += Dvalue[j];
                    least += arc[k][j] * Dvalue[j];
                    Dvalue[j] = 0;
                }
                if(Dvalue[k] < 0 && Dvalue[j] > 0 && abs(Dvalue[k]) < Dvalue[j])
                {

                    B[k] = average;
                    B[j] += Dvalue[k];
                    Dvalue[j] += Dvalue[k];
                    least += arc[k][j] * abs(Dvalue[k]);
                    Dvalue[k] = 0;
                }
            }
        }
        cout << least << endl;int mark[M] = {0};
            int l =0;
            for(int j = 1;j<n && j!=k;++j)
            {
                int distancemin = arc[k][0];
                if(arc[k][j] < distancemin )
                {
                    distancemin = arc[k][j];
                    mark[l] = j;
                    ++l;
                }
            }
        //
        */
        for(int i =0;i<counting;++i)
        {
            int k =FindMin(B,n);
            int mark[M] = {0};
            }int l =0;
            for(int j = 1;j<n && j!=k;++j)
            {
                int distancemin = arc[k][0];
                if(arc[k][j] < distancemin )
                {int mark[M] = {0};
            int l =0;
            for(int j = 1;j<n && j!=k;++j)
            {
                int distancemin = arc[k][0];
                if(arc[k][j] < distancemin )
                {
                    distancemin = arc[k][j];
                    mark[l] = j;
                    ++l;
                }
            }
                    distancemin = arc[k][j];
                    mark[l] = j;
                    ++l;
                }
            }
            for(int i =0;i<)
        }
    }
    return 0;
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值