UPC-游戏智商+ 路标 (动态规划+DFS)
都是细节处理,就直接放在一篇博客里了
游戏智商
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
熊的智商高还是猴子的智商高,这或许是一个很难考究的问题。故事里,吉吉国王一直标榜自己是最聪明最伟大的猴子国王,他的毛毛也是这么坚信。而我们的熊大和熊二却一直相信他们熊熊才是最聪明的。于是,在导游光头强的建议下,他们决定来一场 pk。
Pk 的内容是这样的,有 n 个格子,每个格子从左到右的编号依次是 1 到 n(编号也是位置),每个格子上都有不同美味值的水果(猴子们和熊们都很喜欢吃水果,所以水果对他们来说很有吸引力)。他们从位置 0 开始出发,手上有 AB 两种卡片,A 卡有 na 张,B 卡片有nb 张。每次他们可以用掉一张卡片,然后往前跳若干格,跳的格子数就是卡片上的数字。每跳到一个格子上,就可以吃掉对应格子里面的水果,获得水果的美味值。当然了,我们会保证当卡片用完的时候,一定刚好跳到第 n 个格子上。卡片一定要用完,不能有剩余。
游戏的结果就是在相同的情况下,谁能获得的水果美味值总和最大。熊熊们想要赢得这个比赛,于是熊二请求你的帮助。如果你可以帮助他算出最大值,他甚至可以把他最心爱的蜂蜜分享给你。
输入
输入第一行是3个整数n,na,nb,va,vb,n表示格子的总数,na表示A种卡片的数量,nb表示B种卡片的数量,va表示A种卡片上的数,vb表示B种卡片上的数。保证n一定等于nava+nbvb。
接下来n个整数,表示每个格子上水果的美味值,注意美味值有可能是负数。
输出
输出只有一行一个整数,表示卡片用完的时候,最多可以得到的美味值总和。
样例输入 Copy
3 1 1 2 1
1 2 3
样例输出 Copy
5
提示
共计有20个测试点。
对于第1-6个测试点,保证na=1,nb<=200,美味值都是小于等于10000的正整数。
对于第7-12个测试点,保证1<=na,nb<=12,美味值的绝对值小于等于10000。
对于100%的数据,保证1<=n<=20000,1<=na,nb<=2000,1<=va,vb<=5,va不等于vb,美味值的绝对值不超过1000000。
思路:
dp[i][j]表示用了i张A卡片和j张B卡片所获取的美味值的最大值,状态转移方程:
dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i*va+j*vb]);
dp[i][j]=max(dp[i][j],dp[i][j-1]+a[i*va+j*vb]);
注意一下细节处理
开始数组开小了一直TLE 就离谱
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define I_int ll
#define inf 0x3f3f3f3f
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
char F[200];
inline void out(I_int x) {
if (x == 0) return (void) (putchar('0'));
I_int tmp = x > 0 ? x : -x;
if (x < 0) putchar('-');
int cnt = 0;
while (tmp > 0) {
F[cnt++] = tmp % 10 + '0';
tmp /= 10;
}
while (cnt > 0) putchar(F[--cnt]);
//cout<<" ";
}
const int maxn=2010;
ll dp[maxn][maxn];
///dp[i][j]表示用了i张A卡片和j张B卡片所获取的美味值的最大值
ll n,na,nb,va,vb;
ll a[20010];
void AC(){
n=read();na=read();nb=read();va=read();vb=read();
for(ll i=1;i<=n;i++) a[i]=read();
for(ll i=0;i<=na;i++){
for(ll j=0;j<=nb;j++){
if(i>=1) dp[i][j]=max(dp[i][j],dp[i-1][j]+a[i*va+j*vb]);
if(j>=1) dp[i][j]=max(dp[i][j],dp[i][j-1]+a[i*va+j*vb]);
}
}
out(dp[na][nb]);
}
int main(){
AC();
return 0;
}
路标
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
一天,小Z到OI总部旅游,发现OI总部相当庞大,因此小Z常常迷路。本着“为人民服务”的原则,小Z决定为OI总部制作路标。OI总部由n个OI讨论社组成,有些OI讨论社间有路相连,路是无向的。小Z要在每个OI讨论社竖一个路标。小Z是一个喜欢标新立异的人,他制作的路标分两种:黑路标和白路标。小Z规定:与白路标有路相连的必须是黑路标。由于制作白路标比较省钱,所以他想知道最多有几个OI讨论社的路标为白路标。(注意:OI总部不一定是连通图。)
输入
第一行包括2个整数m和n,表示路的条数和OI讨论社的个数。
接下来的m行,每行两个正整数x和y(x,y<=n且x≠y),表示第x个OI讨论社与第y个OI讨论社有路相连。
输出
共一行,包括1个正整数ans,表示最多有几个OI讨论社的路标为白路标。
样例输入 Copy
1 2
1 2
样例输出 Copy
1
提示
20%数据:n<=3
另有20%数据:m<=3
100%的数据满足:1<=n<=10
思路:
数据范围很小,直接dfs就行,要注意看清题目中说的是白块只能和黑块相连,而黑块则不受限制
读错题wa了5发
#include<bits/stdc++.h>
using namespace std;
const int maxn=110;
int maxx=-1;
int g[maxn][maxn],col[maxn];
int n,m;
///1是白2是黑
bool check(int u){
for(int i=1;i<=n;i++)
if(g[u][i]||g[i][u]){
if(col[i]==1&&col[u]==1) return 0;
}
return 1;
}
void dfs(int u){
if(u==n+1){
int tot=0;
for(int i=1;i<=n;i++) if(col[i]==1) tot++;
maxx=max(maxx,tot);
}
else{
for(int i=1;i<=2;i++){
col[u]=i;
if(check(u)) dfs(u+1);
col[u]=0;
}
}
}
void AC(){
cin>>m>>n;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
g[x][y]=g[y][x]=1;
}
dfs(1);
cout<<maxx<<endl;
}
int main(){
AC();
return 0;
}