POJ1062昂贵的聘礼

第二次做此题:
在次做此题还是做了很长时间,问题在于枚举权限区间时用
for(int i = dfmin; i + m <= djmax: i++)
这事一个多么蠢的错误啊, 如果m很大时, 这个循环都不会执行。肯定是错的, 
正确的做法是:
for(int i = 0; i <= m; i++) {
<span style="white-space:pre">	</span>if(dj[j] >= dj[1] - m + i && dj[j] <= dj[1] + i)
<span style="white-space:pre">		</span>true;
<span style="white-space:pre">	</span>else
<span style="white-space:pre">		</span>false;
就是一根为中心,左右权限变动范围在m内:
除这一点外没什么难的;



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>


using namespace std;


const int M = 150;
const int MAX  = 9999999;
int Map[M][M];
int node[M];
int value[M];
int level[M];
int dist[M];
int lmin, rmax;
int n, m, ans;


void init(){


    ans = MAX;
    rmax = 0;
    lmin = MAX;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++)
            Map[i][j] = MAX;
    }
}


bool check(int x, int y){


    if(level[x] >= level[1] - m + y && level[x] <= level[1] + y)
        return true;
    return false;
}


void Dijstra(int x){


    int index, minn;
    int vist[M];
    for(int i = 1; i <= n; i++){


        vist[i] = 0;
        if(check(i, x)){


          dist[i] = Map[1][i];


        }else {


            dist[i] = MAX;
        }
    }


    dist[1] = 0;
    vist[1] = 1;
    for(int i =1; i <= n; i++){


        minn = MAX;
        for(int j = 1; j <= n; j++){


            if(!vist[j] && dist[j] < minn){


                minn = dist[j];
                index = j;
            }
        }
        if(minn == MAX)
            break;
        vist[index] = 1;
        for(int k = 1; k <= n; k++){


            if(!vist[k] && dist[k] > Map[index][k] + dist[index] && check(index, x) && check(k,x))
                dist[k] = Map[index][k] + dist[index];
        }
    }
    for(int i = 1; i <= n; i++){


        ans = min(ans, dist[i] + value[i]);
    }
}


int main()
{
    int x;
    int a, b;
    while(scanf("%d%d", &m, &n)!= EOF){


        init();
        for(int i = 1; i <= n; i++){


            scanf("%d%d%d", &value[i], &level[i], &x);


            for(int j = 0; j < x; j++){


                scanf("%d%d", &a, &b);
                Map[i][a] = b;
            }
        }
        for(int i = 0; i <= m; i++){


            Dijstra(i);
        }
        printf("%d\n", ans);
    }


    return 0;
}

第一次做此题

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;
/*
本题我开始认为是简单题,用动态规划轻松AC ,但是错几次后发现题意理解错了, 如 一号的等级是3 等级限制是1
  认为在[2 4]间的等级都可以对换,结果可想而知, 真正题意是只选[2 3]的等级, 或[3 4]等级;
  借鉴别人代码;下面就是 dijkastra算法了;
*/

const int MAX = 9999999;
int dp[105][105];
int vist[105];
struct node
{
    int value;
    int dj;
    int num;
}s[105];

int n, m;
int t1, t2;

void init() {

    for(int i = 1; i <= n; i++) {

        for(int j = 1; j <= n; j++) {

            dp[i][j] = MAX;
        }
    }
}

int dijkastra() {

    int cnt[105];
    int dir[105];
    int index;
    int minn;
    dir[1] = 0;
    cnt[1] = 0;

    for(int i = 2; i <= n; i++) {

        dir[i] = MAX;
        cnt[i] = 0;
    }

    for(int i = 1; i < n; i++) {

         minn = MAX;
        for(int j = 1; j <= n; j++)
        {
            if(vist[j] && cnt[j] == 0 && dir[j] < minn) {

                index = j;
                minn = dir[j];
            }
        }
        cnt[index] = 1;
        for(int k = 1; k <= n; k++) {

            if(!cnt[k]&&vist[k] && dir[k] > dir[index] + dp[index][k])
                  dir[k] = dir[index] + dp[index][k];
        }
    }
    minn = MAX;
    for(int i = 1; i <= n; i++) {

        dir[i] += s[i].value;
        if(dir[i] < minn)
            minn = dir[i];
    }
    return minn;
}

int main()
{

    int hao, jinbi;
    while(scanf("%d%d", &m, &n) != EOF) {
         init();
        for(int i = 1; i <= n; i++) {

            scanf("%d%d%d", &s[i].value, &s[i].dj, &s[i].num);
            for(int j = 1; j <= s[i].num; j++) {

                scanf("%d%d", &hao, &jinbi);
                dp[i][hao] = jinbi;
            }
        }
         int ans = MAX;
        for(int i = 0; i <= m; i++) {
            memset(vist, 0, sizeof(vist));
            for(int j = 1; j <= n; j++)
            if(s[j].dj >= s[1].dj - m +i && s[j].dj <= s[1].dj + i)
                  vist[j] = 1;
            int t = dijkastra();
                if(t < ans)
                    ans = t;
        }

        printf("%d\n", ans);

    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值