假期训练六(poj-1753,递归+hdu-2844,多重背包)
Posted 2018zxy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了假期训练六(poj-1753,递归+hdu-2844,多重背包)相关的知识,希望对你有一定的参考价值。
题目一:传送门
题意:有一个4*4的棋盘,每次翻转一个棋子和它的上下左右的四个棋子,判断翻转多少次之后可以变为纯色的棋盘。
思路:总共有C(0,16)+C(1,16)+C(2,16)+……+C(16,16)=2^16次,所以最多有16个棋子被翻动,然后从(0,0)个棋子开始,依次翻转其他棋子,
判断最少要翻转多少个棋子,记着要回溯。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int INF = 99999999; char str[10][10]; int a[10][10],mi,zz[5][2]={0,0, 0,1, 0,-1, 1,0, -1,0}; void turn(int x,int y) { for(int i=0;i<5;i++) { int x1=x+zz[i][0]; int y1=y+zz[i][1]; if(x1>=0&&x1<4&&y1>=0&&y1<4) { a[x1][y1]=!a[x1][y1]; } } } bool pd() { for(int i=0;i<4;i++) { for(int j=0;j<4;j++) if(a[0][0]!=a[i][j]) return false; } return true; } void dfs(int x,int y,int num) { if(pd()) { mi=mi>num?num:mi; return ; } if(x==4) return ; turn(x,y); if(y==3) dfs(x+1,0,num+1); else dfs(x,y+1,num+1); turn(x,y); if(y==3) dfs(x+1,0,num); else dfs(x,y+1,num); } int main(void) { int i,j,n,m; for(i=0;i<4;i++) scanf("%s",str[i]); for(i=0;i<4;i++) { for(j=0;j<4;j++) a[i][j]=str[i][j]==‘b‘?0:1; } mi=INF; dfs(0,0,0); if(mi<=16) printf("%d ",mi); else printf("Impossible "); return 0; }
题目二:传送门
题意:有n个种硬币,最大不超过m,给出每种硬币的价值和数量,求不超过m的情况下能组成多少种价格。
思路:多重背包;
(注意:当时因为审题不清,没理解多少种价格的意思,其实就是dp[i]==i的情况)。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 100100; int val[maxn],num[maxn],dp[maxn],a[maxn*2]; int MAX(int x,int y) { return x>y?x:y; } int main(void) { int n,m,i,j,pt,cnt; while(scanf("%d%d",&n,&m)&&(n+m)) { memset(dp,0,sizeof(dp)); memset(a,0,sizeof(a)); for(i=1;i<=n;i++) scanf("%d",&val[i]); for(pt=1,i=1;i<=n;i++) { scanf("%d",&cnt); for(j=1;j<=cnt;j*=2) { a[pt++]=j*val[i]; cnt-=j; } if(cnt>0) a[pt++]=cnt*val[i]; } for(i=1;i<pt;i++) { for(j=m;j>=a[i];j--) dp[j]=MAX(dp[j],dp[j-a[i]]+a[i]); } int ans=0; for(i=1;i<=m;i++) if(i==dp[i]) ans++; printf("%d ",ans); } return 0; }
以上是关于假期训练六(poj-1753,递归+hdu-2844,多重背包)的主要内容,如果未能解决你的问题,请参考以下文章