1. 程式人生 > >假期訓練六(poj-1753,遞迴+hdu-2844,多重揹包)

假期訓練六(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