zoukankan      html  css  js  c++  java
  • 洛谷 P1282 多米诺骨牌

    这道题很有收获。

    我自己想的时候有想到这是一个背包,但是写的实现非常麻烦,还是错的。

    我想的是在背包的过程中尽量靠近0,但是这样显然有后效性
    而且我思考背包的方式不对。要考虑当前物品有哪几种可能,然后
    比如这道题就是交换或者不交换。先用二维的思考方式,滚动数组
    只是后面的优化。

    后来看了题解,很有收获

    (1)如何防止下标为负数。可以设一个基准数base,然后每次涉及到重量的
    都加上base,这个base的值是负数的最小值。同时注意数组空间就要开大一些。
    这样就避免了负数下标
    (2)先做后统计答案。f[i][j]是前i个骨牌构成和为j的最小交换次数。
    这个答案涉及到最小的数以及次数,一个作维度,一个作值,这样最后
    扫遍数组就可以得出答案。并不是说最后一定要输出f[n][m]什么的。
    这样的思路非常棒。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define REP(i, a, b) for(int i = (a); i < (b); i++) 
    #define _for(i, a, b) for(int i = (a); i <= (b); i++) 
    using namespace std;
    
    const int MAXN = 1123;
    const int base = 5000;
    int a[MAXN], b[MAXN], f[MAXN][base*2+10], n;
    
    int main()
    {
    	scanf("%d", &n);
    	_for(i, 1, n) scanf("%d%d", &a[i], &b[i]);
    	
    	memset(f, 0x3f, sizeof(f));
    	f[0][0+base] = 0;
    	_for(i, 1, n)
    		_for(j, -base, base)
    		{
    			int t = a[i] - b[i];
    			f[i][j+base] = min(f[i-1][j-t+base], f[i-1][j+t+base] + 1); 
    		}
    	
    	_for(j, 0, base)
    	{
    		int t = min(f[n][j+base], f[n][-j+base]);
    		if(t <= 1000)
    		{
    			printf("%d
    ", t);
    			break;
    		}
    	}	
    	
    	return 0;
    }

    滚动数组优化版本(时间甚至还少了。看来空间减少时间也会减少一些。)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define REP(i, a, b) for(int i = (a); i < (b); i++) 
    #define _for(i, a, b) for(int i = (a); i <= (b); i++) 
    using namespace std;
    
    const int MAXN = 1123;
    const int base = 5000;
    int a[MAXN], b[MAXN], f[2][base*2+10], n;
    
    int main()
    {
    	scanf("%d", &n);
    	_for(i, 1, n) scanf("%d%d", &a[i], &b[i]);
    	
    	memset(f, 0x3f, sizeof(f));
    	int p = 1;
    	f[p][0+base] = 0;
    	_for(i, 1, n)
    	{
    		p ^= 1;
    		_for(j, -base, base)
    		{
    			int t = a[i] - b[i];
    			f[p][j+base] = min(f[p^1][j-t+base], f[p^1][j+t+base] + 1); 
    		}
    		
    	}
    	
    	_for(j, 0, base)
    	{
    		int t = min(f[p][j+base], f[p][-j+base]);
    		if(t <= 1000)
    		{
    			printf("%d
    ", t);
    			break;
    		}
    	}	
    	
    	return 0;
    }
  • 相关阅读:
    阿里云服务器搭建之绑定多个域名
    centos7下yum安装mysql
    Mac 升级之后 无法通过域名 SSH 连接
    【课程章节更新】突破 没有支付权限的小程序 完成支付闭环
    每次sudo su切换root用户,都要source /etc/profile
    那些让你震惊的网站
    bootstrap select2使用模态框,搜索框无法输入问题解决
    新浪图片停止外链后的一些解决办法
    Yii2 报错 Headers already sent in
    使用Python Flask 开发微信机器人
  • 原文地址:https://www.cnblogs.com/sugewud/p/9819386.html
Copyright © 2011-2022 走看看