Black And White
— 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.
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 .
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.
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
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
思路:暴搜+剪枝,当前每一种颜色的剩余量如果大于剩余格子数的一半,说明不行,因为如果相互间隔,最多能盛一半的相同的颜色
#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
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.
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.
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
Case #1: 17 Case #2: 74HintIn 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
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.
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.
2 2 2 1 1 2 1 2 3 1 3 1 2 3
Case #1: 10 Case #2: 27HintFor 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.
思路:首先考虑期望值为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
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.
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.
2 3 2 1 2 3 3 3 1 2 3
Case #1: 4 Case #2: 2HintIn 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.
思路: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;
}