2014ACM/ICPC亚洲区北京站hdu5112~5122(dp,dfs)

Black And White


Problem Description
In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into contiguous regions, producing a figure called a map, no more than four colors are required to color the regions of the map so that no two adjacent regions have the same color.
— Wikipedia, the free encyclopedia

In this problem, you have to solve the 4-color problem. Hey, I’m just joking.

You are asked to solve a similar problem:

Color an N × M chessboard with K colors numbered from 1 to K such that no two adjacent cells have the same color (two cells are adjacent if they share an edge). The i-th color should be used in exactly c i cells.

Matt hopes you can tell him a possible coloring.
 

Input
The first line contains only one integer T (1 ≤ T ≤ 5000), which indicates the number of test cases.

For each test case, the first line contains three integers: N, M, K (0 < N, M ≤ 5, 0 < K ≤ N × M ).

The second line contains K integers c i (c i > 0), denoting the number of cells where the i-th color should be used.

It’s guaranteed that c 1 + c 2 + · · · + c K = N × M .
 

Output
For each test case, the first line contains “Case #x:”, where x is the case number (starting from 1).

In the second line, output “NO” if there is no coloring satisfying the requirements. Otherwise, output “YES” in one line. Each of the following N lines contains M numbers seperated by single whitespace, denoting the color of the cells.

If there are multiple solutions, output any of them.
 

Sample Input
  
  
4 1 5 2 4 1 3 3 4 1 2 2 4 2 3 3 2 2 2 3 2 3 2 2 2
 

Sample Output
  
  
Case #1: NO Case #2: YES 4 3 4 2 1 2 4 3 4 Case #3: YES 1 2 3 2 3 1 Case #4: YES 1 2 2 3 3 1
 
题意:用K种颜色填充N*M的格子,相邻的格子颜色不能相同,找出解决方案

思路:暴搜+剪枝,当前每一种颜色的剩余量如果大于剩余格子数的一半,说明不行,因为如果相互间隔,最多能盛一半的相同的颜色

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=30;
int N,M,K;
int c[maxn];
int ans[maxn][maxn],vis[maxn];
int flag;
void dfs(int x,int y,int sum)
{
    if(sum==0)
    {
        flag=true;
        return ;
    }
    for(int i=1;i<=K;i++)
        if(c[i]>(sum+1)/2)return;
    for(int i=1;i<=K;i++)
    {
        if(!c[i])continue;
        if(ans[x-1][y]==i||ans[x][y-1]==i)continue;
        c[i]--;
        ans[x][y]=i;
        if(y<M)dfs(x,y+1,sum-1);
        else dfs(x+1,1,sum-1);
        if(flag)return;
        c[i]++;
    }
    return;
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&N,&M,&K);
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=K;i++)scanf("%d",&c[i]);
        printf("Case #%d:\n",cas++);
        flag=false;
        dfs(1,1,N*M);
        if(!flag)printf("NO\n");
        else
        {
            printf("YES\n");
            for(int i=1;i<=N;i++)
            {
                bool first=true;
                for(int j=1;j<=M;j++)
                {
                    if(first)first=false;
                    else printf(" ");
                    printf("%d",ans[i][j]);
                }
                printf("\n");
            }
        }
    }
    return 0;
}

Dire Wolf



Problem Description
Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not all, Dire Wolves appear to originate from Draenor.
Dire wolves look like normal wolves, but these creatures are of nearly twice the size. These powerful beasts, 8 - 9 feet long and weighing 600 - 800 pounds, are the most well-known orc mounts. As tall as a man, these great wolves have long tusked jaws that look like they could snap an iron bar. They have burning red eyes. Dire wolves are mottled gray or black in color. Dire wolves thrive in the northern regions of Kalimdor and in Mulgore.
Dire wolves are efficient pack hunters that kill anything they catch. They prefer to attack in packs, surrounding and flanking a foe when they can.
— Wowpedia, Your wiki guide to the World of Warcra

Matt, an adventurer from the Eastern Kingdoms, meets a pack of dire wolves. There are N wolves standing in a row (numbered with 1 to N from left to right). Matt has to defeat all of them to survive.

Once Matt defeats a dire wolf, he will take some damage which is equal to the wolf’s current attack. As gregarious beasts, each dire wolf i can increase its adjacent wolves’ attack by b i. Thus, each dire wolf i’s current attack consists of two parts, its basic attack ai and the extra attack provided by the current adjacent wolves. The increase of attack is temporary. Once a wolf is defeated, its adjacent wolves will no longer get extra attack from it. However, these two wolves (if exist) will become adjacent to each other now.

For example, suppose there are 3 dire wolves standing in a row, whose basic attacks ai are (3, 5, 7), respectively. The extra attacks b i they can provide are (8, 2, 0). Thus, the current attacks of them are (5, 13, 9). If Matt defeats the second wolf first, he will get 13 points of damage and the alive wolves’ current attacks become (3, 15).

As an alert and resourceful adventurer, Matt can decide the order of the dire wolves he defeats. Therefore, he wants to know the least damage he has to take to defeat all the wolves.
 

Input
The first line contains only one integer T , which indicates the number of test cases. For each test case, the first line contains only one integer N (2 ≤ N ≤ 200).

The second line contains N integers a i (0 ≤ a i ≤ 100000), denoting the basic attack of each dire wolf.

The third line contains N integers b i (0 ≤ b i ≤ 50000), denoting the extra attack each dire wolf can provide.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1), y is the least damage Matt needs to take.
 

Sample Input
  
  
2 3 3 5 7 8 2 0 10 1 3 5 7 9 2 4 6 8 10 9 4 1 2 1 2 1 4 5 1
 

Sample Output
 
 
Case #1: 17 Case #2: 74
Hint
In the first sample, Matt defeats the dire wolves from left to right. He takes 5 + 5 + 7 = 17 points of damage which is the least damage he has to take.


题意:每一个狼有一个attack,还可以给他旁边的狼提供一个extra attacks,猎人设计一个狼,得到他的attack和extra attacks,问猎人得到的最小的值是多少

思路:区间dp,dp[i][j]=dp[i][k-1]+dp[k+1][j]+a[k]+b[l-1]+b[r+1];

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=210;
const int INF=0x3f3f3f3f;
typedef long long LL;
int N;
int a[maxn],b[maxn];
LL dp[maxn][maxn];
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&N);
        for(int i=1;i<=N;i++)scanf("%d",&a[i]);
        for(int i=1;i<=N;i++)scanf("%d",&b[i]);
        memset(dp,INF,sizeof(dp));
        for(int i=0;i<=N+1;i++)
            for(int j=0;j<=N+1;j++)
                if(i>j)dp[i][j]=0;
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j+i-1<=N;j++)
            {
                int l=j,r=j+i-1;
                for(int k=l;k<=r;k++)
                    dp[l][r]=min(dp[l][r],dp[l][k-1]+dp[k+1][r]+a[k]+b[l-1]+b[r+1]);
            }
        }
        printf("Case #%d: %I64d\n",cas++,dp[1][N]);
    }
    return 0;
}


hdu5117

Fluorescent



Problem Description
Matt, a famous adventurer who once defeated a pack of dire wolves alone, found a lost court. Matt finds that there are N fluorescent lights which seem to be the stars from the firmament. What’s more, there are M switches that control these fluorescent lights. Each switch is connected to a group of lights. When Matt touches a switch, all the lights connected to it will change their states (turning the dark on, turning the bright off).

Initially, all the fluorescent lights are dark. For each switch, Matt will touch it with probability 1 .

As a curious gentleman, Matt wants to calculate E[X3], where X represents the number of bright lights at the end, E[X3] represents the expectation of cube of X.
 

Input
The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains N, M (1 ≤ N, M ≤ 50), denoting the number of fluorescent lights (numbered from 1 to N ) and the number of switches (numbered from 1 to M ).

M lines follow. The i-th line begins with an integer Ki (1 ≤ K i ≤ N ). K i distinct integers l ij(1 ≤ l ij ≤ N ) follow, denoting the fluorescent lights that the i-th switch controls.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y is the answer. To avoid rounding error, the answer you should output is:

E[X3] × 2M mod (109 + 7)
 

Sample Input
  
  
2 2 2 1 1 2 1 2 3 1 3 1 2 3
 

Sample Output
  
  
Case #1: 10 Case #2: 27
Hint
For the first sample, there’re 4 possible situations: All the switches is off, no light is bright, X^3 = 0. Only the first switch is on, the first light is bright, X^3 = 1. Only the second switch is on, all the lights are bright, X^3 = 8. All the switches is on, the second lights are bright, X^3 = 1. Therefore, the answer is E[X^3] × 2^2 mod (10^9 + 7) = 10. For the second sample, there’re 2 possible situations: The switches is off, no light is bright, X^3 = 0. The switches is on, all the lights are bright, X^3 = 27. Therefore, the answer is E[X^3] × 2^1 mod (10^9 + 7) = 27.
 
题意:N盏灯,M个开关,每个开关控制一些等,求E[X3]*2^Mmod(1e9+7)

思路:首先考虑期望值为E(x)*2^m的情况,不难想到,用0表示灯灭1表示灯亮,也就是简单的状压的思想,分别递推求出每个灯亮的情况有多少种方法。

对于期望值为E(x^3)*2^m的拓展,其实就可以变成一个数学展开模型。

X=(X0+X1+X2+X3+...+Xn-1), Xi表示i号灯是灭是亮。

X^3=(X0+X1+X2+X3+...+Xn-1)^3 数学展开以后其实就是每个Cijk*Xi*Xj*Xk (0<=i,j,k<n),C是常数表示ijk的这样排列有多少种,不妨设i<=j<=k,如果i=j=k就取1,i!=j!=k就取6,因为A(3,3)等于6,如果i=j!=k || i!=j=k 就取3,因为A(3,3)/2!=3。

所以算个状压dp[si][sj][sk]表示当前i j k三灯亮灭状态为si sj sk,压缩成状态S,可以用m个开关控制状态转移。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10;
const int SIGMA_SIZE=8;
const int MOD=1e9+7;
typedef long long LL;
LL dp[maxn][maxn];
int N,M;
int a[55][55];
void solve(int cas)
{
    memset(dp,0,sizeof(dp));
    dp[0][0]=1;
    int cur=1;
    LL ans=0;
    for(int i=0;i<N;i++)
    {
        for(int j=i;j<N;j++)
        {
            for(int k=j;k<N;k++)
            {
                memset(dp,0,sizeof(dp));
                dp[0][0]=1;cur=1;

                for(int p=0;p<M;p++,cur^=1)
                {
                    int tmp=0;
                    if(a[p][i])tmp|=1;
                    if(a[p][j])tmp|=2;
                    if(a[p][k])tmp|=4;
                    for(int t=0;t<SIGMA_SIZE;t++)
                        dp[cur][t]=(dp[cur^1][t]+dp[cur^1][t^tmp])%MOD;
                }
                if(i!=j&&j!=k&&i!=k)dp[cur^1][7]*=6;
                else if((i==j&&j!=k)||(i==k&&i!=j)||j==k&&j!=i)
                    dp[cur^1][7]*=3;
                ans=(ans+dp[cur^1][7])%MOD;;
            }
        }
    }
    printf("Case #%d: %I64d\n",cas,ans);
}
int main()
{
    int T,K,x,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        memset(a,0,sizeof(a));
        for(int i=0;i<M;i++)
        {
            scanf("%d",&K);
            for(int j=0;j<K;j++)
            {
                scanf("%d",&x);
                a[i][x-1]=1;
            }
        }
        solve(cas++);
    }
    return 0;
}

hdu5119

Happy Matt Friends



Problem Description
Matt has N friends. They are playing a game together.

Each of Matt’s friends has a magic number. In the game, Matt selects some (could be zero) of his friends. If the xor (exclusive-or) sum of the selected friends’magic numbers is no less than M , Matt wins.

Matt wants to know the number of ways to win.
 

Input
The first line contains only one integer T , which indicates the number of test cases.

For each test case, the first line contains two integers N, M (1 ≤ N ≤ 40, 0 ≤ M ≤ 10 6).

In the second line, there are N integers ki (0 ≤ k i ≤ 10 6), indicating the i-th friend’s magic number.
 

Output
For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1) and y indicates the number of ways where Matt can win.
 

Sample Input
  
  
2 3 2 1 2 3 3 3 1 2 3
 

Sample Output
  
  
Case #1: 4 Case #2: 2
Hint
In the first sample, Matt can win by selecting: friend with number 1 and friend with number 2. The xor sum is 3. friend with number 1 and friend with number 3. The xor sum is 2. friend with number 2. The xor sum is 2. friend with number 3. The xor sum is 3. Hence, the answer is 4.
 
题意:给出N个数,选一些数是他们的异或和小于等于M,有多少种方法

思路:dp[i][j]表示前i个数,异或和为j有多少种情况,因为数据大,所以用滚动数组

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=1050100;
typedef long long LL;
LL dp[2][maxn];
int N,M,a[50];
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=N;i++)
            scanf("%d",&a[i]);
        dp[0][0]=1;
        for(int i=1;i<=N;i++)
        {
            for(int j=0;j<1048576;j++)
                dp[i%2][j]=dp[(i-1)%2][j]+dp[(i-1)%2][j^a[i]];
        }
        LL ans=0;
        for(int i=M;i<1048576;i++)
            ans+=dp[N%2][i];
        printf("Case #%d: %I64d\n",cas++,ans);
    }
    return 0;
}








  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值