Codeforces Round #216 (Div. 2)(好)

A. Valera and Plates

Valera is a lazy student. He has m clean bowls andk clean plates.

Valera has made an eating plan for the next n days. As Valera is lazy, he will eat exactly one dish per day. At that, in order to eat a dish, he needs exactly oneclean plate or bowl. We know that Valera can cook only two types of dishes. He can eat dishes of the first type from bowls and dishes of the second type from either bowls or plates.

When Valera finishes eating, he leaves a dirty plate/bowl behind. His life philosophy doesn't let him eat from dirty kitchenware. So sometimes he needs to wash his plate/bowlbefore eating. Find the minimum number of times Valera will need to wash a plate/bowl, if he acts optimally.

Input

The first line of the input contains three integers n,m, k (1 ≤ n, m, k ≤ 1000) — the number of the planned days, the number of clean bowls and the number of clean plates.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 2). Ifai equals one, then on dayi Valera will eat a first type dish. If ai equals two, then on dayi Valera will eat a second type dish.

Output

Print a single integer — the minimum number of times Valera will need to wash a plate/bowl.

Sample test(s)
Input
3 1 1
1 2 1
Output
1
Input
4 3 1
1 1 1 1
Output
1
Input
3 1 2
2 2 2
Output
0
Input
8 2 2
1 2 1 2 1 2 1 2
Output
4
题意:有两种食物,一种食物只能用碗吃,另一种既可以用碗也可以用碟子,给出每天吃哪种食物,问最少刷几次餐具。
思路:贪心,第二种食物尽量用碟子吃,不够再用碗。
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    int x,ans=0;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        if(x==1)
        {
            if(m<=0)ans++;
            else m--;
        }
        else
        {
            if(k<=0&&m<=0) ans++;
            else if(k>0)k--;
            else if(m>0) m--;
        }
    }
    cout<<ans<<endl;
    return 0;
}

B. Valera and Contest

Valera loves to participate in competitions. Especially in programming contests. Today he has participated in the contest with his team, consisting of n students (including Valera). This contest was an individual competition, so each student in the team solved problems individually.

After the contest was over, Valera was interested in results. He found out that:

  • each student in the team scored at least l points and at most r points;
  • in total, all members of the team scored exactly sall points;
  • the total score of the k members of the team who scored the most points is equal to exactly sk; more formally, if a1, a2, ..., an is the sequence of points earned by the team of students in the non-increasing order (a1 ≥ a2 ≥ ... ≥ an), then sk = a1 + a2 + ... + ak.

However, Valera did not find out exactly how many points each of n students scored. Valera asked you to recover any distribution of scores between the students of the team, such that all the conditions above are met.

Input

The first line of the input contains exactly six integers n, k, l, r, sall, sk (1 ≤ n, k, l, r ≤ 1000; l ≤ r; k ≤ n; 1 ≤ sk ≤ sall ≤ 106).

It's guaranteed that the input is such that the answer exists.

Output

Print exactly n integers a1, a2, ..., an — the number of points each student scored. If there are multiple solutions, you can print any of them. You can print the distribution of points in any order.

Sample test(s)
Input
5 3 1 3 13 9
Output
2 3 2 3 3 
Input
5 3 1 3 15 9
Output
3 3 3 3 3 
题意:n个人比赛,每个人的分数在l到r之间,知道前k大的分数之和是sk,总的分数之和是sall,让你输出一种可能的结果。
下面是代码:
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=1010;
int n,k,l,r,sall,sk;
int ans[maxn];
int main()
{
    cin>>n>>k>>l>>r>>sall>>sk;
    int res=sk%k;
    int tmp=0;
    for(int i=1; i<=k; i++)
        ans[tmp++]=sk/k+(res==0?0:(res--,1));
    sk=sall-sk;
    if(n-k>0)
    {
        res=sk%(n-k);
        for(int i=1; i<=n-k; i++)
            ans[tmp++]=sk/(n-k)+(res==0?0:(res--,1));
    }
    bool first=true;
    for(int i=0; i<n; i++)
    {
        if(first)
        {
            cout<<ans[i];
            first=false;
        }
        else cout<<' '<<ans[i];
    }
    cout<<endl;
    return 0;
}

C. Valera and Elections

The city Valera lives in is going to hold elections to the city Parliament.

The city has n districts and n - 1 bidirectional roads. We know that from any district there is a path along the roads to any other district. Let's enumerate all districts in some way by integers from 1 to n, inclusive. Furthermore, for each road the residents decided if it is the problem road or not. A problem road is a road that needs to be repaired.

There are n candidates running the elections. Let's enumerate all candidates in some way by integers from 1 to n, inclusive. If the candidate number i will be elected in the city Parliament, he will perform exactly one promise — to repair all problem roads on the way from the i-th district to the district 1, where the city Parliament is located.

Help Valera and determine the subset of candidates such that if all candidates from the subset will be elected to the city Parliament, all problem roads in the city will be repaired. If there are several such subsets, you should choose the subset consisting of the minimum number of candidates.

Input

The first line contains a single integer n (2 ≤ n ≤ 105) — the number of districts in the city.

Then n - 1 lines follow. Each line contains the description of a city road as three positive integers xi, yi, ti (1 ≤ xi, yi ≤ n, 1 ≤ ti ≤ 2) — the districts connected by the i-th bidirectional road and the road type. If ti equals to one, then the i-th road isn't the problem road; if ti equals to two, then the i-th road is the problem road.

It's guaranteed that the graph structure of the city is a tree.

Output

In the first line print a single non-negative number k — the minimum size of the required subset of candidates. Then on the second line print k space-separated integers a1, a2, ... ak — the numbers of the candidates that form the required subset. If there are multiple solutions, you are allowed to print any of them.

Sample test(s)
Input
5
1 2 2
2 3 2
3 4 2
4 5 2
Output
1
5 
Input
5
1 2 1
2 3 2
2 4 1
4 5 1
Output
1
3 
Input
5
1 2 2
1 3 2
1 4 2
1 5 2
Output
4
5 4 3 2
 
题意:有n个地区,n-1条路,有的路需要修,有的路不需要修,有n个候选人,如果第i个被选中,则它会把从i到1的
所有需要新修的路修好,问最少有多少候选人才能把所有需要修的路修好,并打印出是那些候选人。
思路:dfs从1出发,如果下一个节点不需要修理并且当前路径需要修理,则保存当前节点,如果下一个节点需要修理,则不需要保存
下面是代码:
#include<iostream>
#include<vector>
#include<cstdio>
using namespace std;
const int maxn=100010;
vector<int> path[maxn],ans,repair[maxn];
int n;
bool dfs(int x,int parent)
{
    bool needToRepair=false;
    for(int i=0;i<path[x].size();i++)
    {
        int u=path[x][i];
        if(u!=parent)
        {
            bool nextNeedToRepair=dfs(u,x);
            if(!nextNeedToRepair&&(repair[x][i]==2))
            {
                ans.push_back(u);
                needToRepair=true;
            }
            if(nextNeedToRepair) needToRepair=true;
        }
    }
    return needToRepair;
}
int main()
{
    int x,y,t;
    cin>>n;
    for(int i=1;i<n;i++)
    {
        cin>>x>>y>>t;
        path[x].push_back(y);
        path[y].push_back(x);
        repair[x].push_back(t);
        repair[y].push_back(t);
    }
    dfs(1,-1);
    cout<<ans.size()<<endl;
    bool first=true;
    for(int i=0;i<ans.size();i++)
    {
        if(first){cout<<ans[i];first=false;}
        else cout<<" "<<ans[i];
    }
    cout<<endl;
    return 0;
}

D. Valera and Fools

注意题意:所有fools都向编号最小的fool开枪;但每个fool都不会笨到想自己开枪,所以编号最小的fool向编号次小的fool开枪;

所以只需记录编号最小的两位成员即可代表一种状态;当然当只剩一个fool时,次小编号是不存在的出界元素。

编号最小的两个fools只有四种状态:a活b活,a死b死,a活b死,a死b活;注意状态转移条件。

记忆化搜索即可(算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。)

需要注意所有的子弹手同时射出的
#include<cstdio>
#include<cstring>
#include<iostream>
#define  N 3010
using namespace std;
int p[N],maxp[N];
int vis[N][N];   //访问标记
int n,k,cnt=0;
void dfs(int a,int b,int t)   //a最小,b次小,t记录开枪次数
{
    if(vis[a][b])  return;
    vis[a][b]=1;
    cnt++;
    if(t==k||b>=n)  return;
    if(p[a])   //若a的概率不为0,则b就可能killed
    {
        if(maxp[b])  dfs(b+1,b+2,t+1);    //a,b都killed
        if(maxp[b]!=100)  dfs(a,b+1,t+1);  //b killed
    }
    //若a的概率不为100,则b就可能living;若b~n的最大概率不为0,则a就可能killed
    if(p[a]!=100 && maxp[b]!=0)  dfs(b,b+1,t+1);
}
int main()
{
    int i,j;
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        memset(maxp,0,sizeof(maxp));
        memset(vis,0,sizeof(vis));
        cnt=0;
        for(i=0; i<n; i++)  scanf("%d",&p[i]);
        for(i=n-1; i>=0; i--) maxp[i]=max(maxp[i+1],p[i]); //记录从i至n的最大概率值
        dfs(0,1,0);
        printf("%d\n",cnt);
    }
    return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值