zoukankan      html  css  js  c++  java
  • UVA 11578

    题目链接:11578 - Situp Benches

    题意:健♂身♂房有两个仰卧起坐坐垫,每次调整角度要花费10元/10度,每次使用要花费15,如今给定n个人的时间顺序,和所希望的角度,求最少花费
    思路:dp,dp[i][j][k]表示第i个人,一个角度为j,还有一个为k的最小花费,一个人用和两个人用的情况分开讨论,然后记录dp状态转移路径。这个输出路径让这题变得麻烦了不少。只是机智的我还是把它搞♂出♂来♂了。
    代码:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define min(a,b) ((a)<(b)?(a):(b))
    const int N = 10005;
    int t, n, i, j, k, dp[N][5][5], ans, an[N];
    struct Stu {
    	int t, l, id;
    } s[N];
    
    struct Out {
    	int n, l, r, out1, out2;
    } out[N][5][5];
    
    bool cmpt(Stu a, Stu b) {
    	return a.t < b.t;
    }
    
    bool cmpid(Stu a, Stu b) {
    	return a.id < b.id;
    }
    
    void print(int n, int l, int r) {
    	Out next = out[n][l][r];
    	if (n == 0) return;
    	if (next.out2 != -1) {
    		an[s[n - 1].id] = next.out1;
    		an[s[n].id] = next.out2;
    	}
    	else {
    		an[s[n].id] = next.out1;
    	}
    	print(next.n, next.l, next.r);
    }
    
    int main() {
    	scanf("%d", &t);
    	while (t--) {
    		ans = INF;
    		memset(dp, INF, sizeof(dp));
    		dp[0][0][0] = 0;
    		scanf("%d", &n);
    		for (i = 1; i <= n; i++) {
    			scanf("%d%d", &s[i].t, &s[i].l);
    			s[i].l = s[i].l / 10 - 1;
    			s[i].id = i;
    		}
    		sort(s + 1, s + n + 1, cmpt);
    		for (i = 1; i <= n; i++) {
    			int tmp1 = s[i].l;
    			if (i == n || s[i].t != s[i + 1].t) {
    				for (j = 0; j < 5; j++) {
    					for (k = 0; k < 5; k++) {
    						if (dp[i][tmp1][k] > dp[i - 1][j][k] + abs(tmp1 - j) * 10) {
    							dp[i][tmp1][k] = dp[i - 1][j][k] + abs(tmp1 - j) * 10;
    							out[i][tmp1][k].l = j; out[i][tmp1][k].r = k; out[i][tmp1][k].n = i - 1;
    							out[i][tmp1][k].out1 = 1; out[i][tmp1][k].out2 = -1;
    						}
    						if (dp[i][j][tmp1] > dp[i - 1][j][k] + abs(tmp1 - k) * 10) {
    							dp[i][j][tmp1] = dp[i - 1][j][k] + abs(tmp1 - k) * 10;
    							out[i][j][tmp1].l = j; out[i][j][tmp1].r = k; out[i][j][tmp1].n = i - 1;
    							out[i][j][tmp1].out1 = 2; out[i][j][tmp1].out2 = -1;
    						}
    					}
    				}
    			}
    			else {
    				int tmp2 = s[i + 1].l;
    				for (j = 0; j < 5; j++) {
    					for (k = 0; k < 5; k++) {
    						if (dp[i + 1][tmp1][tmp2] > dp[i - 1][j][k] + abs(tmp1 - j) * 10 + abs(tmp2 - k) * 10) {
    							dp[i + 1][tmp1][tmp2] = dp[i - 1][j][k] + abs(tmp1 - j) * 10 + abs(tmp2 - k) * 10;
    							out[i + 1][tmp1][tmp2].l = j; out[i + 1][tmp1][tmp2].r = k; out[i + 1][tmp1][tmp2].n = i - 1;
    							out[i + 1][tmp1][tmp2].out1 = 1; out[i + 1][tmp1][tmp2].out2 = 2;
    						}
    						if (dp[i + 1][tmp2][tmp1] > dp[i - 1][j][k] + abs(tmp2 - j) * 10 + abs(tmp1 - k) * 10) {
    							dp[i + 1][tmp2][tmp1] = dp[i - 1][j][k] + abs(tmp2 - j) * 10 + abs(tmp1 - k) * 10;
    							out[i + 1][tmp2][tmp1].l = j; out[i + 1][tmp2][tmp1].r = k; out[i + 1][tmp2][tmp1].n = i - 1;
    							out[i + 1][tmp2][tmp1].out1 = 2; out[i + 1][tmp2][tmp1].out2 = 1;
    						}
    					}
    				}
    				i++;
    			}
    		}
    		int lv, rv;
    		for (j = 0; j < 5; j++) {
    			for (k = 0; k < 5; k++) {
    				if (ans > dp[n][j][k] + j * 10 + k * 10) {
    					ans = dp[n][j][k] + j * 10 + k * 10;
    					lv = j; rv = k;
    				}
    			}
    		}
    		printf("%d
    ", ans + 15 * n);
    		print(n, lv, rv);
    		for (i = 1; i <= n; i++)
    			printf("%d
    ", an[i]);
    	}
    	return 0;
    }


  • 相关阅读:
    值得收藏的146条经典民间偏方[转]
    删除暴风文件夹内的stormliv.exe
    【转】VLAN技术浅谈
    [转载]双击.dsw文件时另开VC6.0,而不会关掉原来已打开的项目的解决办法(转载)
    JVM系列1:Java内存区域
    并发系列3:Lock锁以及核心类AQS
    并发系列1:并发基础知识
    JVM系列2:垃圾收集器与内存分配策略
    JVM系列3:类加载机制
    源码解析之AQS源码解析
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4015613.html
Copyright © 2011-2022 走看看