1.codeforce-----Bicolorings
题意:在 2xn 的表中只能放两个颜色,求可分成m个区域的个数
三维数组DP解决
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
using namespace std;
#define inf 0x3f3f3f3f
const long long mod=998244353;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
long long dp[1010][2010][5];
int main(int argc, char** argv)
{
int n,m;
cin>>n>>m;
memset(dp,0,sizeof(dp));
dp[1][2][0]=1;
dp[1][3][1]=1;
dp[1][3][2]=1;
dp[1][2][3]=1;
for(int i=1;i<=n;i++)
for(int v=1;v<=m;v++)
{
int j=v+1; //防止数组越界
for(int k=0;k<4;k++)
{
if(k==0)
{
dp[i][j][k]+=dp[i-1][j][0]+dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j-1][3];
dp[i][j][k]%=mod;
}
if(k==1)
{
dp[i][j][k]+=dp[i-1][j-1][0]+dp[i-1][j][1]+dp[i-1][j-2][2]+dp[i-1][j-1][3];
dp[i][j][k]%=mod;
}
if(k==2)
{
dp[i][j][k]+=dp[i-1][j-1][0]+dp[i-1][j-2][1]+dp[i-1][j][2]+dp[i-1][j-1][3];
dp[i][j][k]%=mod;
}
if(k==3)
{
dp[i][j][k]+=dp[i-1][j-1][0]+dp[i-1][j][1]+dp[i-1][j][2]+dp[i-1][j][3];
dp[i][j][k]%=mod;
}
}
}
cout <<(dp[n][m+1][0]+dp[n][m+1][1]+dp[n][m+1][2]+dp[n][m+1][3])%mod<<endl;
return 0;
}
问题 C: Evolution Game
时间限制: 1 Sec 内存限制: 128 MB
题目描述
In the fantasy world of ICPC there are magical beasts. As they grow, these beasts can change form, and every time they do they become more powerful. A beast cannot change form completely arbitrarily though. In each form a beast has n eyes and k horns, and these affect the changes it can make.
A beast can only change to a form with more horns than it currently has.
A beast can only change to a form that has a difference of at most w eyes. So, if the beast currently has n eyes it can change to a form with eyes in range [n - w, n + w].
A beast has one form for every number of eyes between 1 and N, and these forms will also have an associated number of horns. A beast can be born in any form. The question is, how powerful can one of these beasts become? In other words, how many times can a beast change form before it runs out of possibilities?输入
The first line contains two integers, N and w, that indicate, respectively, the maximum eye number, and the maximum eye difference allowed in a change (1 ≤ N ≤ 5000; 0 ≤ w ≤ N).
The next line contains N integers which represent the number of horns in each form. I.e. the ith number, h(i), is the number of horns the form with i eyes has (1 ≤ h(i) ≤ 1 000 000).输出
For each test case, display one line containing the maximum possible number of changes.
样例输入
复制样例数据5 5 5 3 2 1 4
样例输出
4
提示
Start with 1 horn and 4 eyes, and it can change 4 times: (1 horn 4 eyes) -> (2 horns 3 eyes) -> (3 horns 2 eyes) -> (4 horns 5 eyes) -> (5 horns 1 eye).
题目大意:一头怪兽可以变换形态,最大变到N只眼,眼睛能变化的范围是W,即[N-w,N+w]。下面有N个数字,分别代表第i只眼睛的时候对应的角数,问最多可以变化多少个形态,怪物的初始状态随机,问最大的变化状态
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <stdlib.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <bitset>
#include <stack>
#include <queue>
#include <set>
#include <vector>
#include <map>
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
int eye;
int horn;
int res;
};
node arr[5000+50];
int n, w;
int dp(int i)
{
int& ans=arr[i].res;
if(ans>0) return ans;
ans=1;
int e_max=arr[i].eye+w;
int e_min=arr[i].eye-w;
for(int j=1;j<=n;j++)
{
if(arr[j].horn>arr[i].horn&&arr[j].eye<=e_max&&arr[j].eye>=e_min)
ans=max(ans,dp(j)+1);
}
return ans;
}
int main()
{
while(cin >> n>> w)
{
memset(arr,0,sizeof(arr));
for(int i=1; i<=n; i++)
{
cin>>arr[i].horn;
arr[i].eye=i;
arr[i].res=0;
}
for(int i=1;i<=n;i++)
dp(i);
int maxx=-1;
for(int i=1;i<=n;i++)
{
if(arr[i].res>maxx)
maxx=arr[i].res;
}
cout<<maxx-1<<endl;
}
}
3 Winner Winner
时间限制: 1 Sec 内存限制: 128 MB
题目描述
FZU Code Carnival是由福州大学ACM-ICPC培训中心主办的一项计划竞赛。该活动主要包括ACM-ICPC等编程竞赛,力争在未来为参与者提供有趣的代码挑战。
在比赛开始之前,YellowStar想知道哪些球队可能成为赢家。YellowStar计算了每个团队的技能,包括数据结构,动态规划,图论等。为了简化预测模型,YellowStar仅列出M技能,每个团队掌握的技能由长度为M的01序列表示。 1意味着团队已经掌握了这项技能,而0则没有。
如果一支球队比其他球队弱,那么这支球队就无法成为赢家。否则,YellowStar认为球队可能获胜。对于A组和B组的技能(a1,a2,...,aM)(b1,b2,...,bM),如果∀i∈[1,M],ai≤bi和∃i∈[1,M],ai <bi则A组弱于B组 。
由于YellowStar最近忙于为FZU Code Carnival做准备,他没有时间预测哪支球队将成为N队的冠军。所以他要求你写一个程序来计算可能成为赢家的球队数量。
输入:
标准输入以下列格式给出
M N
s1 s2 . . . sN , si的二进制表示表示第i个队伍掌握的技能
1 ≤ N ≤ 2 × 106
1 ≤ M ≤ 20
0 ≤ si < 2M
打印一行表示答案。
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
const int maxn=1024*1024+10;
int arr[maxn];
int vis[maxn];
int m;
int main()
{
int n;
scanf("%d%d",&n,&m);
int x;
for(int i=0; i<n; i++)
{
scanf("%d",&x);
arr[x]++;
}
int num=(1<<m)-1;
int sum=0;
for(int i=num;i>=0;i--)
{
if(!vis[i])
sum+=arr[i];
if(arr[i]!=0||vis[i])
{
for(int j=1;j<(1<<m);j<<=1)
{
if(i&j)
vis[i^j]=1;
}
}
}
printf("%d\n",sum);
return 0;
}
状压DP,从最大的长度,全部由的1的数开始往下分,每次列举少一个1的所有情况,用vis数组标记可以别其他状态覆盖的状态;
4 Team
时间限制: 1 Sec 内存限制: 128 MB
ACM-ICPC是一款有趣的游戏。参加这场比赛的球队必须完全由(不多也不少)三人组成队。每年,许多新成员都将加入FZU ACM团队。如何组建团队成为一个大问题。
今年有3*N名成员。每个成员都有一个能力值Wi。如果三个不同的成员x,y,z组成一个团队,该团队的力量是Wx,Wy,Wz的最小值。
有M对关系,他们之间是好朋友。如果成员A和成员B是最好的朋友,他们必须在同一个团队中。我们希望组建N支球队,并获得这N支球队的最大总和。你能帮助我们吗?
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=3*1000+10;
typedef long long ll;
ll a[maxn];
ll b[maxn];
ll dp[maxn][maxn];
int fa[maxn];
int Find(int x)
{
return fa[x]==-1?x:fa[x]=Find(fa[x]);
}
void Union(int x,int y)
{
int t1=Find(x);
int t2=Find(y);
if(t1!=t2)
{
fa[t2]=t1;
a[t1]=min(a[t1],a[t2]);
b[t1]+=b[t2];
b[t2]=0;
}
}
int main()
{
int n,m;
memset(fa,-1,sizeof(fa));
scanf("%d%d",&n,&m);
int n2=n*3;
for(int i=1;i<=n2;i++)
{
scanf("%lld",&a[i]);
b[i]=1;
}
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Union(x,y);
}
int ta=0;
int tb=0;
ll ans=0;
for(int i=1;i<=n2;i++)
{
if(b[i]==1) a[ta++]=a[i];
if(b[i]==2) b[tb++]=a[i];
if(b[i]==3) ans+=a[i];
if(b[i]>=4)
{
printf("-1\n");
return 0;
}
}
sort(a,a+ta);
sort(b,b+tb);
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(int i=0;i<=ta;i++)
for(int j=0;j<=tb;j++)
{
if(dp[i][j]!=-1)
{
dp[i+3][j]=max(dp[i+3][j],dp[i][j]+a[i]);
dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]+min(a[i],b[j]));
}
}
//dp[i][j] i表示一个人一组的选了i个,两个人一组的选了j个; 原来的状态决定之后的状态
if(dp[ta][tb]==-1)
printf("-1\n");
else
printf("%lld\n",ans+dp[ta][tb]);
return 0;
}