假期训练六(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\n",mi);
    else printf("Impossible\n");
    return 0;
}
View Code

题目二:传送门

题意:有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\n",ans);
    }
    return 0;
} 
View Code

猜你喜欢

转载自www.cnblogs.com/2018zxy/p/10260980.html
今日推荐