1337 Greedy C

思路错了,没办法解决分支的问题。想了想,应该是个插头dp。 电脑清文件,在这里备份下代码。说不定还以后用得上

#include <bits/stdc++.h>
using namespace std;
int mp[15][15];
int vis[15][15];
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int sum = 1, m, tem;
set<int> st[70];
vector<int> p(70);
vector<pair<int,int> > E[100];
int book[10];
int ans = -0x3f3f3f3f;
bool ck1 = false;
int  ss,xx,yy ;
void dfs2(int s,int nowans) {
    if(s == ss) ck1 =true;
    if(nowans > ans && ck1 == true) ans = nowans;
    int now = s;
    for(int i = 0; i < (int)E[now].size(); i++) {
        int next = E[now][i].first;
        if(book[next] == 0) {
            book[next] = 1;
           if(next == ss) ck1 =true;
            dfs2(next, nowans + E[now][i].second);
            book[next] = 0;
        }

    }
      if(s == ss) ck1 = false;
}
void dfs(int x,int y) {
    for(int i = 0; i < 4;i++) {
        int tx = x + dx[i];
        int ty = y + dy[i];
        if(tx >= 1 && tx <= m && ty >= 1 && ty <=m)
            if(mp[tx][ty] >=0 && vis[tx][ty] == 0) {
                vis[tx][ty] = sum;
                tem += mp[tx][ty];
                dfs(tx,ty);
        }
    }
}
int main(void) {

    cin >> m >> xx >> yy;
    for(int i = 1; i<= m; i++)
        for(int j = 1; j <= m; j++)
            cin >> mp[i][j];
    for(int i = 1; i <= m; i++)
        for(int j = 1; j  <= m; j++) {
            if(mp[i][j] >= 0 && vis[i][j] == 0) {
                vis[i][j] = sum;
                tem = mp[i][j];
                dfs(i,j);
                p[sum] = tem;
                sum++;
            }
            else if(mp[i][j] < 0 && vis[i][j] == 0) {
                vis[i][j] = sum;
                p[sum] = mp[i][j];
                sum++;
            }
    }
    cout << endl;
    for(int i = 1; i <= m; i++) {
        for(int j = 1; j <= m; j++) {
            cout << vis[i][j] << " ";
        }
        cout <<endl;
    }
    cout << endl;
    for(int x = 1; x <= m; x++) {
        for(int y = 1; y <= m; y++)
            for(int k = 0; k < 4; k++){
               int  tx = x + dx[k];
               int  ty = y + dy[k];
                if(tx >= 1 && tx <= m && ty >= 1 && ty <=m && vis[x][y] != vis[tx][ty] ) {
                        st[vis[x][y]].insert(vis[tx][ty]);
                }

            }
    }
    for(int i = 1; i < sum; i++) {
        for(auto it = st[i].begin(); it != st[i].end(); ++it) {
                 cout << i << " " << *it << " " << p[*it] << endl;
                 E[i].push_back(make_pair(*it, p[*it]));
        }cout << endl;
    }
    ss = vis[xx][yy];
    for(int i = 1 ; i < sum; i++) {
            memset(book,0,sizeof(book));
            book[i] = 1;
            dfs2(i, p[i]);
    }
    cout << ans << endl;
    return 0;
}


### 回答1: 下面是Codeoforces上题目10E Greedy Change的C代码: ``` #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> using namespace std; const int N=5050, M=25, INF=0x3f3f3f3f; int n, m, ans, minv[M], p[M], vis[M]; int head[N], dis[N], tot=1; struct node { int to, next, w; } e[N<<1]; inline void add(int u, int v, int w) { e[++tot]=(node){v, head[u], w}; head[u]=tot; } inline void spfa() { queue<int> q; memset(dis, 0x3f, sizeof(dis)); dis[0]=0, vis[0]=1, q.push(0); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u]; i; i=e[i].next) { int v=e[i].to; if(dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; if(!vis[v]) vis[v]=1, q.push(v); } } } } int main() { scanf("%d%d", &n, &m); for(int i=1; i<=m; i++) scanf("%d%d", &p[i], &minv[i]); for(int i=1; i<=m; i++) for(int j=minv[i]; j<=n; j++) add(j-minv[i], j, p[i]); spfa(); printf("%d\n", dis[n]); return 0; } ``` 这道题是一道最短路题目,使用spfa算法求解。题目要求我们用最少的钱数买到价值为n的物品,我们可以将每种物品看作一条边,价值为边权,价格为边的费用。我们从0开始建图,对于每一种物品,都从它的最小价值开始连向它的价值的所有整数倍 ### 回答2: 下面是题目10E Greedy Change的C代码: ```c #include <stdio.h> int main() { int n; scanf("%d", &n); // 创建一个数组存储每一个硬币面值 int coins[] = {1, 2, 5, 10, 20, 50, 100, 200}; // 创建一个变量保存最小硬币数 int minCoins = 0; // 从最大面值硬币开始,逐个进行贪心选择 for (int i = sizeof(coins) / sizeof(coins[0]) - 1; i >= 0; i--) { // 当前面值硬币最多能用几枚 int numCoins = n / coins[i]; // 更新总硬币数 minCoins += numCoins; // 更新剩余金额 n -= numCoins * coins[i]; // 如果已达到目标金额,跳出循环 if (n == 0) { break; } } printf("%d\n", minCoins); return 0; } ``` 该代码按照贪心算法的思想,从最大面值的硬币开始,尽可能多地使用当前面值硬币,直到满足目标金额为止。其中`n`是输入的目标金额,`coins`数组保存硬币的面值,`minCoins`保存最少的硬币数。代码通过循环遍历每个面值硬币,计算当前面值硬币最多能使用的数量,更新总硬币数和剩余金额。然后在每次循环的末尾判断剩余金额是否为0,如果是则跳出循环并输出最小硬币数。最后打印输出最小硬币数`minCoins`。 ### 回答3: 下面是Codeforces题目10E Greedy Change的C代码: ```c #include <stdio.h> void greedyChange(int n) { int notes[7] = { 1, 2, 5, 10, 20, 50, 100 }; int count[7] = { 0 }; int i, j; for (i = 6; i >= 0; i--) { count[i] = n / notes[i]; n = n % notes[i]; } for (j = 0; j < 7; j++) { printf("%d ", count[j]); } } int main() { int n; scanf("%d", &n); greedyChange(n); return 0; } ``` 以上代码实现了一个贪心算法,用于计算某个整数n的找零方案。题目要求找零的面值有1、2、5、10、20、50和100。代码首先定义一个 `notes` 数组和一个 `count` 数组分别存储面值和对应的数量。然后,使用贪心算法进行计算,从大到小遍历 `notes` 数组,依次计算每个面值的数量,并更新剩余的找零金额。最后,输出每个面值的数量。在 `main` 函数中,从输入中读取n,并调用 `greedyChange` 函数进行计算和输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值