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

u010660276發表於2014-01-11
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;
}



相關文章