uva 10123 - No Tipping dp 记忆化搜索

这题的题意是 在双脚天平上有N块东西,依次从上面取走一些,最后使得这个天平保持平衡!

解题:

  逆着来依次放入,如果可行那就可以,记得得有木板自身的重量。

/*************************************************************************
    > File Name: 10123.cpp
    > Author: opas
    > Mail: [email protected]
    > Created Time: 2016年10月22日 星期六 22时58分53秒
 ************************************************************************/
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxm = 20;
const int maxn = 1<<maxm;
struct Node {
    int id,weight,dist;
    Node (int l_id = 0, int l_weight = 0, int l_dist = 0)    {
        id = l_id;
        weight = l_weight;
        dist = l_dist;
    }
    bool operator < (const Node A)const {
        if (weight != A.weight ) return weight < A.weight;
        return id < A.id;
    }
}package[maxm];
int dp[maxn];
int weight_val[maxn][4];
int ans[maxm];
void InitVal(int n)    {
    int max_val = 1<<n;
    for(int i = 0; i < max_val; ++ i)    {
        dp[i] = 0;
    }
}
int length ,weight, num_package;
void AddPackage(int per_status ,int now_status, int id)    {
    for ( int i = 0; i < 4; ++ i)
        weight_val[now_status][i] = weight_val[per_status][i];
    if(package[id].dist <= -3)    {
        weight_val[now_status][0] = weight_val[per_status][0] + - ( package[id].dist + 3) * package[id].weight;
        weight_val[now_status][3] = weight_val[per_status][3] + - ( package[id].dist - 3) * package[id].weight;
    }else if(package[id].dist < 3){
        weight_val[now_status][1] = weight_val[per_status][1] + (package[id].dist + 3) * package[id].weight;
        weight_val[now_status][3] = weight_val[per_status][3] + - (package[id].dist - 3) * package[id].weight;
    }else{
        weight_val[now_status][1] = weight_val[per_status][1] + (package[id].dist + 3)*package[id].weight;
        weight_val[now_status][2] = weight_val[per_status][2] + (package[id].dist - 3)*package[id].weight;
    }
}
int CheckPackage(int now_status)    {
    int l_val1 = weight_val[now_status][0];
    int l_val2 = weight_val[now_status][1] +3 * weight;
    if(l_val1 > l_val2){
      return dp[now_status] = 2;
    }
    l_val1 = weight_val[now_status][2];
    l_val2 = weight_val[now_status][3] + 3 * weight;
    if(l_val1 > l_val2) {
        return dp[now_status] = 2;
    }
        return dp[now_status] = 1;
}
int dfs(int now_loc, int now_status)    {
    if(now_loc == num_package)    {
        return 1;
    }
    dp[now_status] = 2;
    for(int i = 0; i< num_package ; ++ i)    {
        if(now_status & (1<<i))
            continue;
        int next_status = now_status | (1<<i);
        if(dp[next_status] == 2) return dp[next_status];
        AddPackage(now_status, next_status, i);
        if(CheckPackage(next_status) == 2)
            continue;
        ans[now_loc] = i;
        if (dfs(now_loc+1, next_status) == 1)    {
            return dp[now_status]=1;
        }
    }
    return 2;
}
int main(){
    for(int cc = 1; ; ++ cc) {
        cin>>length>>weight>>num_package;
        if(length + weight + num_package == 0)
                break;
        InitVal(num_package);
        for(int i = 0; i < num_package; ++ i)    {
            int l_weight , l_dist;
            scanf("%d%d",&l_dist, &l_weight);
            l_dist = l_dist * 2;
            package[i] = Node(i, l_weight, l_dist);
        }
        printf("Case %d:\n",cc);
        if( dfs(0 , 0) == 1) {
            for(int i = num_package - 1; i >= 0; -- i)    {
                printf("%d %d\n", package[ans[i]].dist/2, package[ans[i]].weight);
            }
        }else{
            printf("Impossible\n");
        }
    }
    return 0;
}

时间: 2024-10-29 10:46:06

uva 10123 - No Tipping dp 记忆化搜索的相关文章

UVa 10817 (状压DP + 记忆化搜索) Headmaster&#39;s Headache

题意: 一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师. 每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老师教而且使得总工资最少. 分析: 因为s很小,所以可以用状态压缩. dp(i, s1, s2)表示考虑了前i个人,有一个人教的课程的集合为s1,至少有两个人教的集合为s2. 在递归的过程中,还有个参数s0,表示还没有人教的科目的集合. 其中m0, m1, s0, s1, s2的计算用到位运算,还

uva 10626 Buying Coke (DP + 记忆化搜索)

Problem D Buying Coke Input: Standard Input Output: Standard Output Time Limit: 2 Seconds I often buy Coca-Cola from the vending machine at work. Usually I buy several cokes at once, since my working mates also likes coke. A coke in the vending machi

UVa 10599【lis dp,记忆化搜索】

UVa 10599 题意: 给出r*c的网格,其中有些格子里面有垃圾,机器人从左上角移动到右下角,只能向右或向下移动.问机器人能清扫最多多少个含有垃圾的格子,有多少中方案,输出其中一种方案的格子编号.格子编号是从 左上角第一个开始,一行一行的按自然数顺序编.起始行列是第一行第一列.所以例如一个格子的行列号为(ro,co),那么它的编号为bh=(ro-1)*column+co,其中column指这个格子有多少列.(我觉得原题里面有个错误,题目叙述倒数第二行应该是41(6,6)不是41(6,7)).

UVa 1252 (状压DP + 记忆化搜索) Twenty Questions

题意: 有n个长为m的各不相同的二进制数(允许存在前导0),别人已经事先想好n个数中的一个数W,你要猜出这个数. 每次只可以询问该数的第K为是否为1. 问采用最优询问策略,则最少需要询问多少次能保证猜到. 比如有1100 和 0110两个数,只需要询问第一或第三位数是否为1,即可猜中,因此答案为1. 分析: d(s, a)表示已经询问了的集合s,在已经询问了的集合中W中为1的集合为a,还需要询问多少次. 如果下一次询问第k位,则询问次数为: 然后取所有k里的最小值即可. 预处理: 对于每个s和a

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

UVA - 10817 Headmaster&#39;s Headache (状压dp+记忆化搜索)

题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所能教的所有科目. 2.已聘老师必须选,候选老师可选可不选. 3.dfs(cur, subject1, subject2)---求出在当前已选cur个老师,有一个老师教的科目状态为 subject1,有两个及以上老师教的科目状态为 subject2的情况下,最少的雇佣费用. dp[cur][subje

状压DP+记忆化搜索 UVA 1252 Twenty Questions

题目传送门 1 /* 2 题意:给出一系列的01字符串,问最少要问几个问题(列)能把它们区分出来 3 状态DP+记忆化搜索:dp[s1][s2]表示问题集合为s1.答案对错集合为s2时,还要问几次才能区分出来 4 若和答案(自己拟定)相差小于等于1时,证说明已经能区分了,回溯.否则还要加问题再询问 5 */ 6 /************************************************ 7 * Author :Running_Time 8 * Created Time :

UVA - 10913Walking on a Grid(记忆化搜索)

题目:Walking on a Grid 题目大意:给出N * N的矩阵,每个格子里都有一个值,现在要求从(1,1)走到(n, n),只能往下,左,右这三个方向走,并且要求最多只能取k个负数,求这样的要求下能得到的走过格子的值之和最大. 解题思路:记忆化搜索,但是这里要四维的,因为要记录方向,为了防止走回头的路,并且取了几个负数也要记录.然后就是dfs了.状态转移方程:dp[x][y][d][k] = dp[x + dir[i][0]][y + dir[i][1]][i][k1] + G[x][

UVA 10981 - String Morphing(记忆化搜索)

题目链接:10981 - String Morphing 题意:给定开始的字符串,要求根据表格变化成一个字符串,问变化的顺序(注意,不一定要最少步数) 思路:记忆化搜索,用map来存字符串的状态,一开始按最少步数去做TLE,其实只要找到一个符合的就可以了 代码: #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <map> u